From 992930a821a711debbce1fd6a7e4dc4ef0607b1f Mon Sep 17 00:00:00 2001 From: MSuMshk <2039814060@qq.com> Date: Tue, 17 Feb 2026 09:57:26 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E6=B8=85=E7=90=86=E7=A7=9F?= =?UTF-8?q?=E6=88=B7API=E6=97=A7=E6=A8=A1=E5=9D=97=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Api/TakeoutSaaS.TenantApi/Program.cs | 47 +- .../App/Billings/BillingMapping.cs | 200 - .../Commands/BatchUpdateStatusCommand.cs | 25 - .../Billings/Commands/CancelBillingCommand.cs | 19 - .../Commands/ConfirmPaymentCommand.cs | 42 - .../Billings/Commands/CreateBillCommand.cs | 30 - .../Billings/Commands/CreateBillingCommand.cs | 41 - .../GenerateSubscriptionBillingCommand.cs | 15 - .../Commands/ProcessOverdueBillingsCommand.cs | 10 - .../Billings/Commands/RecordPaymentCommand.cs | 41 - .../Commands/UpdateBillStatusCommand.cs | 26 - .../Commands/UpdateBillingStatusCommand.cs | 25 - .../Billings/Commands/VerifyPaymentCommand.cs | 28 - .../App/Billings/Dto/BillDetailDto.cs | 78 - .../App/Billings/Dto/BillDto.cs | 68 - .../App/Billings/Dto/BillingDetailDto.cs | 146 - .../App/Billings/Dto/BillingDtos.cs | 545 -- .../App/Billings/Dto/BillingExportDto.cs | 104 - .../App/Billings/Dto/BillingLineItemDto.cs | 37 - .../App/Billings/Dto/BillingListDto.cs | 114 - .../App/Billings/Dto/BillingStatisticsDto.cs | 91 - .../App/Billings/Dto/BillingTrendPointDto.cs | 27 - .../App/Billings/Dto/PaymentDto.cs | 63 - .../App/Billings/Dto/PaymentRecordDto.cs | 95 - .../BatchUpdateStatusCommandHandler.cs | 110 - .../Handlers/CancelBillingCommandHandler.cs | 36 - .../Handlers/ConfirmPaymentCommandHandler.cs | 99 - .../Handlers/CreateBillCommandHandler.cs | 61 - .../Handlers/CreateBillingCommandHandler.cs | 65 - .../Handlers/ExportBillingsQueryHandler.cs | 44 - ...nerateSubscriptionBillingCommandHandler.cs | 102 - .../Handlers/GetBillDetailQueryHandler.cs | 41 - .../Handlers/GetBillListQueryHandler.cs | 55 - .../Handlers/GetBillingDetailQueryHandler.cs | 236 - .../Handlers/GetBillingListQueryHandler.cs | 250 - .../GetBillingPaymentsQueryHandler.cs | 139 - .../GetBillingStatisticsQueryHandler.cs | 204 - .../GetOverdueBillingsQueryHandler.cs | 172 - .../Handlers/GetTenantPaymentsQueryHandler.cs | 28 - .../ProcessOverdueBillingsCommandHandler.cs | 20 - .../Handlers/RecordPaymentCommandHandler.cs | 81 - .../UpdateBillStatusCommandHandler.cs | 50 - .../UpdateBillingStatusCommandHandler.cs | 54 - .../Handlers/VerifyPaymentCommandHandler.cs | 73 - .../Billings/Queries/ExportBillingsQuery.cs | 19 - .../Billings/Queries/GetBillDetailQuery.cs | 15 - .../App/Billings/Queries/GetBillListQuery.cs | 47 - .../Billings/Queries/GetBillingDetailQuery.cs | 15 - .../Billings/Queries/GetBillingListQuery.cs | 72 - .../Queries/GetBillingPaymentsQuery.cs | 15 - .../Queries/GetBillingStatisticsQuery.cs | 30 - .../Queries/GetOverdueBillingsQuery.cs | 21 - .../Queries/GetTenantPaymentsQuery.cs | 15 - .../ConfirmPaymentCommandValidator.cs | 50 - .../CreateBillingCommandValidator.cs | 73 - .../RecordPaymentCommandValidator.cs | 49 - .../UpdateBillingStatusCommandValidator.cs | 30 - .../Commands/CreateDeliveryOrderCommand.cs | 66 - .../Commands/DeleteDeliveryOrderCommand.cs | 14 - .../Commands/UpdateDeliveryOrderCommand.cs | 71 - .../App/Deliveries/Dto/DeliveryEventDto.cs | 43 - .../App/Deliveries/Dto/DeliveryOrderDto.cs | 89 - .../CreateDeliveryOrderCommandHandler.cs | 72 - .../DeleteDeliveryOrderCommandHandler.cs | 38 - .../GetDeliveryOrderByIdQueryHandler.cs | 64 - .../SearchDeliveryOrdersQueryHandler.cs | 71 - .../UpdateDeliveryOrderCommandHandler.cs | 84 - .../Queries/GetDeliveryOrderByIdQuery.cs | 15 - .../Queries/SearchDeliveryOrdersQuery.cs | 42 - .../CreateDeliveryOrderCommandValidator.cs | 23 - .../SearchDeliveryOrdersQueryValidator.cs | 20 - .../UpdateDeliveryOrderCommandValidator.cs | 24 - ...pApplicationServiceCollectionExtensions.cs | 36 - .../Commands/AdjustInventoryCommand.cs | 46 - .../Commands/DeductInventoryCommand.cs | 35 - .../Commands/LockInventoryCommand.cs | 41 - .../ReleaseExpiredInventoryLocksCommand.cs | 8 - .../Commands/ReleaseInventoryCommand.cs | 35 - .../Commands/UpsertInventoryBatchCommand.cs | 45 - .../App/Inventory/Dto/InventoryBatchDto.cs | 53 - .../App/Inventory/Dto/InventoryItemDto.cs | 99 - .../Handlers/AdjustInventoryCommandHandler.cs | 85 - .../Handlers/DeductInventoryCommandHandler.cs | 110 - .../GetInventoryBatchesQueryHandler.cs | 26 - .../Handlers/GetInventoryItemQueryHandler.cs | 26 - .../Handlers/LockInventoryCommandHandler.cs | 92 - ...easeExpiredInventoryLocksCommandHandler.cs | 60 - .../ReleaseInventoryCommandHandler.cs | 76 - .../UpsertInventoryBatchCommandHandler.cs | 57 - .../App/Inventory/InventoryMapping.cs | 49 - .../Queries/GetInventoryBatchesQuery.cs | 20 - .../Queries/GetInventoryItemQuery.cs | 20 - .../AdjustInventoryCommandValidator.cs | 21 - .../DeductInventoryCommandValidator.cs | 21 - .../LockInventoryCommandValidator.cs | 21 - .../ReleaseInventoryCommandValidator.cs | 21 - .../UpsertInventoryBatchCommandValidator.cs | 22 - .../Commands/AddMerchantDocumentCommand.cs | 17 - .../Commands/CreateMerchantCategoryCommand.cs | 13 - .../Commands/CreateMerchantCommand.cs | 53 - .../Commands/CreateMerchantContractCommand.cs | 15 - .../Commands/DeleteMerchantCategoryCommand.cs | 9 - .../Commands/DeleteMerchantCommand.cs | 14 - .../ReorderMerchantCategoriesCommand.cs | 17 - .../Commands/UpdateMerchantCommand.cs | 50 - .../UpdateMerchantContractStatusCommand.cs | 16 - .../AddMerchantDocumentCommandHandler.cs | 81 - .../CreateMerchantCategoryCommandHandler.cs | 56 - .../Handlers/CreateMerchantCommandHandler.cs | 57 - .../CreateMerchantContractCommandHandler.cs | 85 - .../DeleteMerchantCategoryCommandHandler.cs | 38 - .../Handlers/DeleteMerchantCommandHandler.cs | 36 - .../Handlers/ExportMerchantPdfQueryHandler.cs | 40 - .../GetMerchantAuditHistoryQueryHandler.cs | 35 - .../GetMerchantAuditLogsQueryHandler.cs | 41 - .../Handlers/GetMerchantByIdQueryHandler.cs | 42 - .../GetMerchantCategoriesQueryHandler.cs | 37 - .../GetMerchantChangeHistoryQueryHandler.cs | 35 - .../GetMerchantContractsQueryHandler.cs | 36 - .../Handlers/GetMerchantDetailQueryHandler.cs | 48 - .../GetMerchantDocumentsQueryHandler.cs | 36 - .../Handlers/GetMerchantListQueryHandler.cs | 98 - .../ListMerchantCategoriesQueryHandler.cs | 32 - ...ReorderMerchantCategoriesCommandHandler.cs | 47 - .../Handlers/SearchMerchantsQueryHandler.cs | 70 - .../Handlers/UpdateMerchantCommandHandler.cs | 177 - ...ateMerchantContractStatusCommandHandler.cs | 83 - .../Queries/ExportMerchantPdfQuery.cs | 8 - .../Queries/GetMerchantAuditHistoryQuery.cs | 9 - .../Queries/GetMerchantAuditLogsQuery.cs | 13 - .../Merchants/Queries/GetMerchantByIdQuery.cs | 15 - .../Queries/GetMerchantCategoriesQuery.cs | 8 - .../Queries/GetMerchantChangeHistoryQuery.cs | 10 - .../Queries/GetMerchantContractsQuery.cs | 9 - .../Queries/GetMerchantDetailQuery.cs | 9 - .../Queries/GetMerchantDocumentsQuery.cs | 9 - .../Merchants/Queries/GetMerchantListQuery.cs | 53 - .../Queries/ListMerchantCategoriesQuery.cs | 9 - .../Merchants/Queries/SearchMerchantsQuery.cs | 37 - .../CreateMerchantCommandValidator.cs | 23 - .../SearchMerchantsQueryValidator.cs | 20 - .../UpdateMerchantCommandValidator.cs | 25 - .../App/Orders/Commands/CreateOrderCommand.cs | 117 - .../App/Orders/Commands/DeleteOrderCommand.cs | 14 - .../App/Orders/Commands/OrderItemRequest.cs | 52 - .../App/Orders/Commands/UpdateOrderCommand.cs | 117 - .../App/Orders/Dto/OrderDto.cs | 146 - .../App/Orders/Dto/OrderItemDto.cs | 68 - .../App/Orders/Dto/OrderStatusHistoryDto.cs | 44 - .../App/Orders/Dto/RefundRequestDto.cs | 58 - .../Handlers/CreateOrderCommandHandler.cs | 156 - .../Handlers/DeleteOrderCommandHandler.cs | 39 - .../Handlers/GetOrderByIdQueryHandler.cs | 105 - .../Handlers/SearchOrdersQueryHandler.cs | 92 - .../Handlers/UpdateOrderCommandHandler.cs | 133 - .../App/Orders/Queries/GetOrderByIdQuery.cs | 15 - .../App/Orders/Queries/SearchOrdersQuery.cs | 53 - .../Validators/CreateOrderCommandValidator.cs | 79 - .../Validators/SearchOrdersQueryValidator.cs | 21 - .../Validators/UpdateOrderCommandValidator.cs | 63 - .../Payments/Commands/CreatePaymentCommand.cs | 56 - .../Payments/Commands/DeletePaymentCommand.cs | 14 - .../Payments/Commands/UpdatePaymentCommand.cs | 61 - .../App/Payments/Dto/PaymentDto.cs | 79 - .../App/Payments/Dto/PaymentRefundDto.cs | 49 - .../Handlers/CreatePaymentCommandHandler.cs | 67 - .../Handlers/DeletePaymentCommandHandler.cs | 38 - .../Handlers/GetPaymentByIdQueryHandler.cs | 60 - .../Handlers/SearchPaymentsQueryHandler.cs | 70 - .../Handlers/UpdatePaymentCommandHandler.cs | 77 - .../Payments/Queries/GetPaymentByIdQuery.cs | 15 - .../Payments/Queries/SearchPaymentsQuery.cs | 42 - .../CreatePaymentCommandValidator.cs | 45 - .../SearchPaymentsQueryValidator.cs | 20 - .../UpdatePaymentCommandValidator.cs | 46 - .../Products/Commands/CreateProductCommand.cs | 101 - .../Products/Commands/DeleteProductCommand.cs | 14 - .../Commands/PublishProductCommand.cs | 20 - .../Commands/ReplaceProductAddonsCommand.cs | 20 - .../ReplaceProductAttributesCommand.cs | 20 - .../Commands/ReplaceProductMediaCommand.cs | 20 - .../ReplaceProductPricingRulesCommand.cs | 20 - .../Commands/ReplaceProductSkusCommand.cs | 20 - .../Commands/UnpublishProductCommand.cs | 20 - .../Products/Commands/UpdateProductCommand.cs | 106 - .../App/Products/Dto/ProductAddonGroupDto.cs | 47 - .../App/Products/Dto/ProductAddonOptionDto.cs | 37 - .../Products/Dto/ProductAttributeGroupDto.cs | 42 - .../Products/Dto/ProductAttributeOptionDto.cs | 32 - .../Products/Dto/ProductCategoryMenuDto.cs | 48 - .../App/Products/Dto/ProductDetailDto.cs | 39 - .../App/Products/Dto/ProductDto.cs | 120 - .../App/Products/Dto/ProductMediaAssetDto.cs | 43 - .../App/Products/Dto/ProductPricingRuleDto.cs | 43 - .../App/Products/Dto/ProductSkuDto.cs | 62 - .../App/Products/Dto/StoreMenuDto.cs | 33 - .../Handlers/CreateProductCommandHandler.cs | 78 - .../Handlers/DeleteProductCommandHandler.cs | 40 - .../Handlers/GetProductByIdQueryHandler.cs | 28 - .../Handlers/GetProductDetailQueryHandler.cs | 63 - .../Handlers/GetStoreMenuQueryHandler.cs | 136 - .../Handlers/PublishProductCommandHandler.cs | 49 - .../ReplaceProductAddonsCommandHandler.cs | 74 - .../ReplaceProductAttributesCommandHandler.cs | 77 - .../ReplaceProductMediaCommandHandler.cs | 51 - ...eplaceProductPricingRulesCommandHandler.cs | 52 - .../ReplaceProductSkusCommandHandler.cs | 61 - .../Handlers/SearchProductsQueryHandler.cs | 75 - .../UnpublishProductCommandHandler.cs | 39 - .../Handlers/UpdateProductCommandHandler.cs | 88 - .../App/Products/ProductMapping.cs | 133 - .../Products/Queries/GetProductByIdQuery.cs | 15 - .../Products/Queries/GetProductDetailQuery.cs | 15 - .../App/Products/Queries/GetStoreMenuQuery.cs | 21 - .../Products/Queries/SearchProductsQuery.cs | 47 - .../CreateProductCommandValidator.cs | 29 - .../PublishProductCommandValidator.cs | 19 - .../ReplaceProductAddonsCommandValidator.cs | 31 - ...eplaceProductAttributesCommandValidator.cs | 28 - .../ReplaceProductMediaCommandValidator.cs | 24 - ...laceProductPricingRulesCommandValidator.cs | 23 - .../ReplaceProductSkusCommandValidator.cs | 26 - .../SearchProductsQueryValidator.cs | 20 - .../UnpublishProductCommandValidator.cs | 19 - .../UpdateProductCommandValidator.cs | 30 - .../Commands/CreateQuotaPackageCommand.cs | 46 - .../Commands/DeleteQuotaPackageCommand.cs | 14 - .../Commands/PurchaseQuotaPackageCommand.cs | 30 - .../Commands/UpdateQuotaPackageCommand.cs | 51 - .../UpdateQuotaPackageStatusCommand.cs | 19 - .../App/QuotaPackages/Dto/QuotaPackageDto.cs | 62 - .../QuotaPackages/Dto/QuotaPackageListDto.cs | 47 - .../Dto/TenantQuotaPurchaseDto.cs | 64 - .../QuotaPackages/Dto/TenantQuotaUsageDto.cs | 47 - .../CreateQuotaPackageCommandHandler.cs | 54 - .../DeleteQuotaPackageCommandHandler.cs | 29 - .../GetQuotaPackageListQueryHandler.cs | 41 - .../GetTenantQuotaPurchasesQueryHandler.cs | 43 - .../GetTenantQuotaUsageQueryHandler.cs | 35 - .../PurchaseQuotaPackageCommandHandler.cs | 88 - .../UpdateQuotaPackageCommandHandler.cs | 54 - .../UpdateQuotaPackageStatusCommandHandler.cs | 34 - .../Queries/GetQuotaPackageListQuery.cs | 32 - .../Queries/GetTenantQuotaPurchasesQuery.cs | 26 - .../Queries/GetTenantQuotaUsageQuery.cs | 21 - .../Statistics/Dto/ExpiringSubscriptionDto.cs | 49 - .../Statistics/Dto/QuotaUsageRankingDto.cs | 50 - .../Statistics/Dto/RevenueStatisticsDto.cs | 53 - .../Statistics/Dto/SubscriptionOverviewDto.cs | 42 - .../GetExpiringSubscriptionsQueryHandler.cs | 38 - .../GetQuotaUsageRankingQueryHandler.cs | 39 - .../GetRevenueStatisticsQueryHandler.cs | 71 - .../GetSubscriptionOverviewQueryHandler.cs | 49 - .../Queries/GetExpiringSubscriptionsQuery.cs | 20 - .../Queries/GetQuotaUsageRankingQuery.cs | 21 - .../Queries/GetRevenueStatisticsQuery.cs | 15 - .../Queries/GetSubscriptionOverviewQuery.cs | 11 - .../BatchUpdateBusinessHoursCommand.cs | 20 - .../CreateStoreBusinessHourCommand.cs | 46 - .../App/Stores/Commands/CreateStoreCommand.cs | 126 - .../CreateStoreDeliveryZoneCommand.cs | 45 - .../CreateStoreEmployeeShiftCommand.cs | 46 - .../Commands/CreateStoreHolidayCommand.cs | 51 - .../Commands/CreateStorePickupSlotCommand.cs | 50 - .../CreateStoreQualificationCommand.cs | 46 - .../Commands/CreateStoreStaffCommand.cs | 36 - .../Commands/CreateStoreTableAreaCommand.cs | 30 - .../DeleteStoreBusinessHourCommand.cs | 19 - .../App/Stores/Commands/DeleteStoreCommand.cs | 14 - .../DeleteStoreDeliveryZoneCommand.cs | 19 - .../DeleteStoreEmployeeShiftCommand.cs | 19 - .../Commands/DeleteStoreHolidayCommand.cs | 19 - .../Commands/DeleteStorePickupSlotCommand.cs | 19 - .../DeleteStoreQualificationCommand.cs | 19 - .../Commands/DeleteStoreStaffCommand.cs | 19 - .../Commands/DeleteStoreTableAreaCommand.cs | 19 - .../Commands/DeleteStoreTableCommand.cs | 19 - .../Commands/GenerateStoreTablesCommand.cs | 45 - .../Commands/SubmitStoreAuditCommand.cs | 14 - .../Commands/ToggleBusinessStatusCommand.cs | 31 - .../UpdateStoreBusinessHourCommand.cs | 51 - .../App/Stores/Commands/UpdateStoreCommand.cs | 126 - .../UpdateStoreDeliveryZoneCommand.cs | 50 - .../UpdateStoreEmployeeShiftCommand.cs | 51 - .../Stores/Commands/UpdateStoreFeeCommand.cs | 51 - .../Commands/UpdateStoreHolidayCommand.cs | 56 - .../Commands/UpdateStorePickupSlotCommand.cs | 55 - .../UpdateStoreQualificationCommand.cs | 45 - .../Commands/UpdateStoreStaffCommand.cs | 46 - .../Commands/UpdateStoreTableAreaCommand.cs | 35 - .../Commands/UpdateStoreTableCommand.cs | 46 - .../UpsertStorePickupSettingCommand.cs | 35 - .../BatchUpdateBusinessHoursCommandHandler.cs | 75 - .../Handlers/CalculateStoreFeeQueryHandler.cs | 55 - .../CheckStoreDeliveryZoneQueryHandler.cs | 60 - .../CheckStoreQualificationsQueryHandler.cs | 133 - .../CreateStoreBusinessHourCommandHandler.cs | 57 - .../Handlers/CreateStoreCommandHandler.cs | 114 - .../CreateStoreDeliveryZoneCommandHandler.cs | 65 - .../CreateStoreEmployeeShiftCommandHandler.cs | 72 - .../CreateStoreHolidayCommandHandler.cs | 73 - .../CreateStorePickupSlotCommandHandler.cs | 64 - .../CreateStoreQualificationCommandHandler.cs | 85 - .../CreateStoreStaffCommandHandler.cs | 56 - .../CreateStoreTableAreaCommandHandler.cs | 58 - .../DeleteStoreBusinessHourCommandHandler.cs | 46 - .../Handlers/DeleteStoreCommandHandler.cs | 40 - .../DeleteStoreDeliveryZoneCommandHandler.cs | 46 - .../DeleteStoreEmployeeShiftCommandHandler.cs | 36 - .../DeleteStoreHolidayCommandHandler.cs | 46 - .../DeleteStorePickupSlotCommandHandler.cs | 28 - .../DeleteStoreQualificationCommandHandler.cs | 72 - .../DeleteStoreStaffCommandHandler.cs | 35 - .../DeleteStoreTableAreaCommandHandler.cs | 52 - .../DeleteStoreTableCommandHandler.cs | 36 - .../ExportStoreTableQRCodesQueryHandler.cs | 86 - .../GenerateStoreTablesCommandHandler.cs | 73 - .../GetAvailablePickupSlotsQueryHandler.cs | 83 - .../Handlers/GetStoreByIdQueryHandler.cs | 26 - .../Handlers/GetStoreFeeQueryHandler.cs | 51 - .../GetStorePickupSettingQueryHandler.cs | 37 - .../GetStoreTableContextQueryHandler.cs | 55 - ...ExpiringStoreQualificationsQueryHandler.cs | 287 - .../ListStoreBusinessHoursQueryHandler.cs | 32 - .../ListStoreDeliveryZonesQueryHandler.cs | 32 - .../ListStoreEmployeeShiftsQueryHandler.cs | 37 - .../Handlers/ListStoreHolidaysQueryHandler.cs | 32 - .../ListStorePickupSlotsQueryHandler.cs | 38 - .../ListStoreQualificationsQueryHandler.cs | 37 - .../Handlers/ListStoreStaffQueryHandler.cs | 47 - .../ListStoreTableAreasQueryHandler.cs | 26 - .../Handlers/ListStoreTablesQueryHandler.cs | 39 - .../Handlers/SearchStoresQueryHandler.cs | 57 - .../SubmitStoreAuditCommandHandler.cs | 115 - .../ToggleBusinessStatusCommandHandler.cs | 69 - .../UpdateStoreBusinessHourCommandHandler.cs | 59 - .../Handlers/UpdateStoreCommandHandler.cs | 79 - .../UpdateStoreDeliveryZoneCommandHandler.cs | 65 - .../UpdateStoreEmployeeShiftCommandHandler.cs | 71 - .../Handlers/UpdateStoreFeeCommandHandler.cs | 88 - .../UpdateStoreHolidayCommandHandler.cs | 73 - .../UpdateStorePickupSlotCommandHandler.cs | 57 - .../UpdateStoreQualificationCommandHandler.cs | 79 - .../UpdateStoreStaffCommandHandler.cs | 55 - .../UpdateStoreTableAreaCommandHandler.cs | 59 - .../UpdateStoreTableCommandHandler.cs | 72 - .../UpsertStorePickupSettingCommandHandler.cs | 63 - .../Stores/Queries/CalculateStoreFeeQuery.cs | 30 - .../Queries/CheckStoreDeliveryZoneQuery.cs | 25 - .../Queries/CheckStoreQualificationsQuery.cs | 15 - .../Queries/ExportStoreTableQRCodesQuery.cs | 25 - .../Queries/GetAvailablePickupSlotsQuery.cs | 21 - .../App/Stores/Queries/GetStoreByIdQuery.cs | 15 - .../App/Stores/Queries/GetStoreFeeQuery.cs | 15 - .../Queries/GetStorePickupSettingQuery.cs | 15 - .../Queries/GetStoreTableContextQuery.cs | 15 - .../ListExpiringStoreQualificationsQuery.cs | 35 - .../Queries/ListStoreBusinessHoursQuery.cs | 15 - .../Queries/ListStoreDeliveryZonesQuery.cs | 15 - .../Queries/ListStoreEmployeeShiftsQuery.cs | 30 - .../Stores/Queries/ListStoreHolidaysQuery.cs | 15 - .../Queries/ListStorePickupSlotsQuery.cs | 15 - .../Queries/ListStoreQualificationsQuery.cs | 15 - .../App/Stores/Queries/ListStoreStaffQuery.cs | 26 - .../Queries/ListStoreTableAreasQuery.cs | 15 - .../Stores/Queries/ListStoreTablesQuery.cs | 26 - .../App/Stores/Queries/SearchStoresQuery.cs | 62 - .../Services/GeoJsonValidationResult.cs | 22 - .../Stores/Services/IDeliveryZoneService.cs | 22 - .../Services/IGeoJsonValidationService.cs | 14 - .../Services/IStoreFeeCalculationService.cs | 18 - .../Stores/Services/IStoreSchedulerService.cs | 23 - ...atchUpdateBusinessHoursCommandValidator.cs | 40 - .../Validators/BusinessHourValidators.cs | 65 - .../CalculateStoreFeeQueryValidator.cs | 26 - .../CheckStoreDeliveryZoneQueryValidator.cs | 20 - ...CreateStoreBusinessHourCommandValidator.cs | 21 - .../Validators/CreateStoreCommandValidator.cs | 33 - ...CreateStoreDeliveryZoneCommandValidator.cs | 24 - ...reateStoreEmployeeShiftCommandValidator.cs | 22 - .../CreateStoreHolidayCommandValidator.cs | 41 - .../CreateStorePickupSlotCommandValidator.cs | 23 - ...reateStoreQualificationCommandValidator.cs | 42 - .../CreateStoreStaffCommandValidator.cs | 21 - .../CreateStoreTableAreaCommandValidator.cs | 21 - .../DeleteStorePickupSlotCommandValidator.cs | 19 - ...eleteStoreQualificationCommandValidator.cs | 19 - .../GenerateStoreTablesCommandValidator.cs | 23 - .../GetStoreTableContextQueryValidator.cs | 18 - .../Validators/SearchStoresQueryValidator.cs | 20 - .../SubmitStoreAuditCommandValidator.cs | 18 - .../ToggleBusinessStatusCommandValidator.cs | 29 - ...UpdateStoreBusinessHourCommandValidator.cs | 22 - .../Validators/UpdateStoreCommandValidator.cs | 31 - ...UpdateStoreDeliveryZoneCommandValidator.cs | 25 - ...pdateStoreEmployeeShiftCommandValidator.cs | 23 - .../UpdateStoreFeeCommandValidator.cs | 87 - .../UpdateStoreHolidayCommandValidator.cs | 42 - .../UpdateStorePickupSlotCommandValidator.cs | 24 - ...pdateStoreQualificationCommandValidator.cs | 26 - .../UpdateStoreStaffCommandValidator.cs | 22 - .../UpdateStoreTableAreaCommandValidator.cs | 22 - .../UpdateStoreTableCommandValidator.cs | 22 - ...psertStorePickupSettingCommandValidator.cs | 21 - .../BatchExtendSubscriptionsCommand.cs | 72 - .../Commands/BatchSendReminderCommand.cs | 45 - .../Commands/ChangeSubscriptionPlanCommand.cs | 34 - .../Commands/ExtendSubscriptionCommand.cs | 29 - .../Commands/ProcessAutoRenewalCommand.cs | 33 - .../ProcessRenewalRemindersCommand.cs | 33 - .../ProcessSubscriptionExpiryCommand.cs | 33 - .../Commands/UpdateSubscriptionCommand.cs | 28 - .../UpdateSubscriptionStatusCommand.cs | 30 - .../App/Subscriptions/Dto/QuotaUsageDto.cs | 52 - .../Dto/SubscriptionDetailDto.cs | 106 - .../Dto/SubscriptionHistoryDto.cs | 80 - .../Subscriptions/Dto/SubscriptionListDto.cs | 95 - .../BatchExtendSubscriptionsCommandHandler.cs | 135 - .../BatchSendReminderCommandHandler.cs | 104 - .../ChangeSubscriptionPlanCommandHandler.cs | 95 - .../ExtendSubscriptionCommandHandler.cs | 69 - .../GetSubscriptionDetailQueryHandler.cs | 138 - .../GetSubscriptionListQueryHandler.cs | 61 - .../ProcessAutoRenewalCommandHandler.cs | 137 - .../ProcessRenewalRemindersCommandHandler.cs | 117 - ...ProcessSubscriptionExpiryCommandHandler.cs | 63 - .../UpdateSubscriptionCommandHandler.cs | 48 - .../UpdateSubscriptionStatusCommandHandler.cs | 46 - .../Queries/GetSubscriptionDetailQuery.cs | 15 - .../Queries/GetSubscriptionListQuery.cs | 52 - .../Commands/CreateSystemParameterCommand.cs | 35 - .../Commands/DeleteSystemParameterCommand.cs | 14 - .../Commands/UpdateSystemParameterCommand.cs | 40 - .../Dto/SystemParameterDto.cs | 57 - .../CreateSystemParameterCommandHandler.cs | 64 - .../DeleteSystemParameterCommandHandler.cs | 33 - .../GetSystemParameterByIdQueryHandler.cs | 35 - .../SearchSystemParametersQueryHandler.cs | 69 - .../UpdateSystemParameterCommandHandler.cs | 66 - .../Queries/GetSystemParameterByIdQuery.cs | 9 - .../Queries/SearchSystemParametersQuery.cs | 41 - .../CreateSystemParameterCommandValidator.cs | 21 - .../SearchSystemParametersQueryValidator.cs | 21 - .../UpdateSystemParameterCommandValidator.cs | 22 - .../Commands/CheckTenantQuotaCommand.cs | 26 - .../CreateTenantAnnouncementCommand.cs | 67 - .../DeleteTenantAnnouncementCommand.cs | 19 - .../Commands/MarkAnnouncementAsReadCommand.cs | 22 - .../MarkTenantNotificationReadCommand.cs | 20 - .../Commands/PublishAnnouncementCommand.cs | 24 - .../Commands/RevokeAnnouncementCommand.cs | 24 - .../Commands/SelfRegisterTenantCommand.cs | 46 - .../SubmitTenantVerificationCommand.cs | 67 - .../UpdateTenantAnnouncementCommand.cs | 53 - .../Tenants/Commands/UpdateTenantCommand.cs | 53 - .../App/Tenants/Dto/QuotaCheckResultDto.cs | 29 - .../App/Tenants/Dto/QuotaUsageHistoryDto.cs | 45 - .../App/Tenants/Dto/SelfRegisterResultDto.cs | 47 - .../App/Tenants/Dto/TenantAnnouncementDto.cs | 113 - .../App/Tenants/Dto/TenantBillingDto.cs | 63 - .../App/Tenants/Dto/TenantNotificationDto.cs | 58 - .../App/Tenants/Dto/TenantPackageDto.cs | 107 - .../App/Tenants/Dto/TenantProgressDto.cs | 42 - .../App/Tenants/Dto/TenantVerificationDto.cs | 104 - .../CheckTenantQuotaCommandHandler.cs | 162 - .../CreateTenantAnnouncementCommandHandler.cs | 99 - .../DeleteTenantAnnouncementCommandHandler.cs | 46 - .../GetAnnouncementByIdQueryHandler.cs | 71 - .../GetPublicTenantPackagesQueryHandler.cs | 36 - .../Handlers/GetTenantBillQueryHandler.cs | 46 - .../GetTenantPackageByIdQueryHandler.cs | 23 - .../Handlers/GetTenantProgressQueryHandler.cs | 55 - .../GetTenantQuotaUsageHistoryQueryHandler.cs | 186 - .../GetTenantsAnnouncementsQueryHandler.cs | 129 - .../GetUnreadAnnouncementsQueryHandler.cs | 76 - .../MarkAnnouncementAsReadCommandHandler.cs | 100 - ...arkTenantNotificationReadCommandHandler.cs | 58 - .../PublishAnnouncementCommandHandler.cs | 84 - .../RevokeAnnouncementCommandHandler.cs | 77 - .../Handlers/SearchTenantBillsQueryHandler.cs | 53 - .../SearchTenantNotificationsQueryHandler.cs | 59 - .../SelfRegisterTenantCommandHandler.cs | 140 - .../SubmitTenantVerificationCommandHandler.cs | 80 - .../UpdateTenantAnnouncementCommandHandler.cs | 90 - .../Handlers/UpdateTenantCommandHandler.cs | 81 - .../Queries/GetAnnouncementByIdQuery.cs | 20 - .../Queries/GetPublicTenantPackagesQuery.cs | 21 - .../App/Tenants/Queries/GetTenantBillQuery.cs | 20 - .../Queries/GetTenantPackageByIdQuery.cs | 15 - .../Tenants/Queries/GetTenantProgressQuery.cs | 17 - .../GetTenantQuotaUsageHistoryQuery.cs | 43 - .../Queries/GetTenantsAnnouncementsQuery.cs | 62 - .../Queries/GetUnreadAnnouncementsQuery.cs | 21 - .../Tenants/Queries/SearchTenantBillsQuery.cs | 42 - .../Queries/SearchTenantNotificationsQuery.cs | 37 - .../AnnouncementTargetContextFactory.cs | 58 - .../App/Tenants/Targeting/TargetTypeFilter.cs | 218 - .../TenantAnnouncementTargetTypePolicy.cs | 49 - .../App/Tenants/TenantMapping.cs | 141 - .../CreateAnnouncementCommandValidator.cs | 45 - ...etTenantQuotaUsageHistoryQueryValidator.cs | 27 - .../PublishAnnouncementCommandValidator.cs | 24 - .../RevokeAnnouncementCommandValidator.cs | 24 - .../SelfRegisterTenantCommandValidator.cs | 22 - .../UpdateAnnouncementCommandValidator.cs | 34 - .../Abstractions/ICsvDictionaryParser.cs | 17 - .../Abstractions/IDictionaryAppService.cs | 26 - .../Abstractions/IDictionaryCache.cs | 24 - .../Abstractions/IDictionaryHybridCache.cs | 26 - .../Abstractions/IJsonDictionaryParser.cs | 17 - .../Contracts/CreateDictionaryGroupRequest.cs | 39 - .../Contracts/CreateDictionaryItemRequest.cs | 51 - .../Contracts/DictionaryBatchQueryRequest.cs | 15 - .../Contracts/DictionaryGroupQuery.cs | 49 - .../Contracts/DictionaryImportRequest.cs | 34 - .../DictionaryOverrideHiddenItemsRequest.cs | 15 - .../DictionaryOverrideSortOrderRequest.cs | 15 - .../Contracts/UpdateDictionaryGroupRequest.cs | 36 - .../Contracts/UpdateDictionaryItemRequest.cs | 47 - .../DictionaryServiceCollectionExtensions.cs | 26 - .../Dictionary/Models/DictionaryGroupDto.cs | 73 - .../Models/DictionaryImportResultDto.cs | 53 - .../Dictionary/Models/DictionaryImportRow.cs | 47 - .../Dictionary/Models/DictionaryItemDto.cs | 63 - .../Dictionary/Models/LabelOverrideDto.cs | 118 - .../Dictionary/Models/OverrideConfigDto.cs | 36 - .../Services/DictionaryAppService.cs | 459 - .../Services/DictionaryCacheKeys.cs | 44 - .../Services/DictionaryCommandService.cs | 343 - .../Services/DictionaryImportExportService.cs | 483 -- .../DictionaryLabelOverrideService.cs | 180 - .../Dictionary/Services/DictionaryMapper.cs | 46 - .../Services/DictionaryMergeService.cs | 84 - .../Services/DictionaryOverrideService.cs | 322 - .../Services/DictionaryQueryService.cs | 246 - .../Services/DictionaryValueConverter.cs | 46 - .../CreateDictionaryGroupValidator.cs | 25 - .../Validators/I18nValueValidator.cs | 32 - .../UpdateDictionaryItemValidator.cs | 23 - .../IAdminPasswordResetTokenStore.cs | 25 - .../IIdentityOperationLogPublisher.cs | 17 - .../Abstractions/ILoginRateLimiter.cs | 10 - .../Identity/Abstractions/IMiniAuthService.cs | 13 - .../Abstractions/IWeChatAuthService.cs | 36 - .../Commands/AssignUserRolesCommand.cs | 19 - .../BatchIdentityUserOperationCommand.cs | 26 - .../Commands/BindRolePermissionsCommand.cs | 24 - .../ChangeIdentityUserStatusCommand.cs | 25 - .../Commands/CloneRoleTemplateCommand.cs | 40 - .../Commands/CopyRoleTemplateCommand.cs | 30 - .../Commands/CreateIdentityUserCommand.cs | 66 - .../Identity/Commands/CreateMenuCommand.cs | 81 - .../Commands/CreatePermissionCommand.cs | 40 - .../Identity/Commands/CreateRoleCommand.cs | 30 - .../Commands/CreateRoleTemplateCommand.cs | 35 - .../Commands/DeleteIdentityUserCommand.cs | 19 - .../Identity/Commands/DeleteMenuCommand.cs | 14 - .../Commands/DeletePermissionCommand.cs | 14 - .../Identity/Commands/DeleteRoleCommand.cs | 19 - .../Commands/DeleteRoleTemplateCommand.cs | 14 - .../InitializeRoleTemplatesCommand.cs | 15 - .../ResetAdminPasswordByTokenCommand.cs | 20 - .../ResetIdentityUserPasswordCommand.cs | 20 - .../Commands/RestoreIdentityUserCommand.cs | 19 - .../Commands/UpdateIdentityUserCommand.cs | 56 - .../Identity/Commands/UpdateMenuCommand.cs | 86 - .../Commands/UpdatePermissionCommand.cs | 40 - .../Identity/Commands/UpdateRoleCommand.cs | 30 - .../Commands/UpdateRoleTemplateCommand.cs | 35 - .../Events/IdentityUserOperationLogMessage.cs | 47 - .../IdentityServiceCollectionExtensions.cs | 28 - .../Handlers/AssignUserRolesCommandHandler.cs | 34 - ...atchIdentityUserOperationCommandHandler.cs | 314 - .../BindRolePermissionsCommandHandler.cs | 53 - .../ChangeIdentityUserStatusCommandHandler.cs | 146 - .../CloneRoleTemplateCommandHandler.cs | 73 - .../CopyRoleTemplateCommandHandler.cs | 129 - .../CreateIdentityUserCommandHandler.cs | 190 - .../Handlers/CreateMenuCommandHandler.cs | 57 - .../CreatePermissionCommandHandler.cs | 70 - .../Handlers/CreateRoleCommandHandler.cs | 81 - .../CreateRoleTemplateCommandHandler.cs | 55 - .../DeleteIdentityUserCommandHandler.cs | 120 - .../Handlers/DeleteMenuCommandHandler.cs | 34 - .../DeletePermissionCommandHandler.cs | 42 - .../Handlers/DeleteRoleCommandHandler.cs | 48 - .../DeleteRoleTemplateCommandHandler.cs | 35 - .../GetIdentityUserDetailQueryHandler.cs | 96 - .../Handlers/GetRoleTemplateQueryHandler.cs | 31 - .../GetUserPermissionsQueryHandler.cs | 87 - .../InitializeRoleTemplatesCommandHandler.cs | 62 - .../Handlers/ListMenusQueryHandler.cs | 27 - .../Handlers/ListRoleTemplatesQueryHandler.cs | 36 - .../Handlers/MenuDetailQueryHandler.cs | 27 - .../Identity/Handlers/MenuMapper.cs | 129 - .../Handlers/PermissionTreeQueryHandler.cs | 74 - ...ResetAdminPasswordByTokenCommandHandler.cs | 64 - ...ResetIdentityUserPasswordCommandHandler.cs | 97 - .../RestoreIdentityUserCommandHandler.cs | 84 - .../Handlers/RoleDetailQueryHandler.cs | 78 - .../RoleTemplatePermissionsQueryHandler.cs | 40 - .../SearchIdentityUsersQueryHandler.cs | 139 - .../Handlers/SearchPermissionsQueryHandler.cs | 74 - .../Handlers/SearchRolesQueryHandler.cs | 75 - .../SearchUserPermissionsQueryHandler.cs | 129 - .../Identity/Handlers/TemplateMapper.cs | 35 - .../UpdateIdentityUserCommandHandler.cs | 166 - .../Handlers/UpdateMenuCommandHandler.cs | 55 - .../UpdatePermissionCommandHandler.cs | 72 - .../Handlers/UpdateRoleCommandHandler.cs | 66 - .../UpdateRoleTemplateCommandHandler.cs | 45 - .../Identity/MenuPolicy.cs | 12 - .../Models/IdentityUserBatchOperation.cs | 32 - .../Identity/PermissionPolicy.cs | 12 - .../Queries/GetIdentityUserDetailQuery.cs | 20 - .../Identity/Queries/GetRoleTemplateQuery.cs | 15 - .../Queries/GetUserPermissionsQuery.cs | 15 - .../Identity/Queries/ListMenusQuery.cs | 12 - .../Queries/ListRoleTemplatesQuery.cs | 15 - .../Identity/Queries/MenuDetailQuery.cs | 15 - .../Identity/Queries/PermissionTreeQuery.cs | 15 - .../Identity/Queries/RoleDetailQuery.cs | 20 - .../Queries/RoleTemplatePermissionsQuery.cs | 15 - .../Queries/SearchIdentityUsersQuery.cs | 77 - .../Queries/SearchPermissionsQuery.cs | 32 - .../Identity/Queries/SearchRolesQuery.cs | 37 - .../Queries/SearchUserPermissionsQuery.cs | 36 - .../Identity/Services/MiniAuthService.cs | 148 - ...chIdentityUserOperationCommandValidator.cs | 24 - .../CreateIdentityUserCommandValidator.cs | 37 - .../SearchIdentityUsersQueryValidator.cs | 28 - .../UpdateIdentityUserCommandValidator.cs | 37 - .../Messaging/Abstractions/IEventPublisher.cs | 12 - .../Messaging/EventRoutingKeys.cs | 17 - .../Messaging/Events/OrderCreatedEvent.cs | 32 - .../Messaging/Events/PaymentSucceededEvent.cs | 32 - .../MessagingServiceCollectionExtensions.cs | 20 - .../Messaging/Services/EventPublisher.cs | 14 - .../Abstractions/IVerificationCodeService.cs | 19 - .../Contracts/SendVerificationCodeRequest.cs | 27 - .../Contracts/SendVerificationCodeResponse.cs | 17 - .../VerifyVerificationCodeRequest.cs | 25 - .../SmsServiceCollectionExtensions.cs | 27 - .../Sms/Options/VerificationCodeOptions.cs | 33 - .../Sms/Services/VerificationCodeService.cs | 155 - .../Abstractions/IFileStorageService.cs | 19 - .../Storage/Contracts/DirectUploadRequest.cs | 37 - .../Storage/Contracts/DirectUploadResponse.cs | 32 - .../Storage/Contracts/FileUploadResponse.cs | 22 - .../Storage/Contracts/UploadFileRequest.cs | 48 - .../Storage/Enums/UploadFileType.cs | 37 - .../StorageServiceCollectionExtensions.cs | 20 - .../Extensions/UploadFileTypeParser.cs | 46 - .../Storage/Services/FileStorageService.cs | 282 - .../Repositories/IDeliveryRepository.cs | 87 - .../ICacheInvalidationLogRepository.cs | 29 - .../IDictionaryGroupRepository.cs | 104 - .../IDictionaryImportLogRepository.cs | 22 - .../Repositories/IDictionaryItemRepository.cs | 64 - .../IDictionaryLabelOverrideRepository.cs | 65 - .../Repositories/IDictionaryRepository.cs | 99 - .../ITenantDictionaryOverrideRepository.cs | 47 - .../Dictionary/ValueObjects/I18nValue.cs | 151 - .../Repositories/IMiniUserRepository.cs | 37 - .../Repositories/IRoleTemplateRepository.cs | 74 - .../Repositories/IInventoryRepository.cs | 95 - .../IMerchantCategoryRepository.cs | 66 - .../Services/IMerchantExportService.cs | 26 - .../Orders/Repositories/IOrderRepository.cs | 122 - .../Repositories/IPaymentRepository.cs | 86 - .../Repositories/IProductRepository.cs | 268 - .../Stores/Events/StoreApprovedEvent.cs | 22 - .../Stores/Events/StoreForceClosedEvent.cs | 27 - .../Stores/Events/StoreRejectedEvent.cs | 32 - .../Stores/Events/StoreSubmittedEvent.cs | 22 - .../ISystemParameterRepository.cs | 65 - .../Tenants/Enums/BillingExportFormat.cs | 22 - .../Tenants/Events/AnnouncementPublished.cs | 22 - .../Tenants/Events/AnnouncementRevoked.cs | 17 - .../Repositories/IQuotaPackageRepository.cs | 131 - .../Repositories/IStatisticsRepository.cs | 112 - .../Repositories/ISubscriptionRepository.cs | 382 - .../ITenantAnnouncementReadRepository.cs | 53 - .../ITenantAnnouncementRepository.cs | 97 - .../ITenantQuotaUsageHistoryRepository.cs | 23 - .../Tenants/Services/IBillingDomainService.cs | 64 - .../Tenants/Services/IBillingExportService.cs | 33 - .../AppServiceCollectionExtensions.cs | 86 - .../App/Options/AppSeedOptions.cs | 32 - .../App/Options/DictionarySeedGroupOptions.cs | 50 - .../App/Options/DictionarySeedItemOptions.cs | 39 - .../App/Options/SystemParameterSeedOptions.cs | 37 - .../App/Options/TenantSeedOptions.cs | 46 - .../App/Persistence/AppDataSeeder.cs | 494 -- .../TenantBillingStatementConfiguration.cs | 51 - .../TenantPaymentConfiguration.cs | 40 - .../Repositories/TenantBillingRepository.cs | 655 -- .../Repositories/TenantPaymentRepository.cs | 105 - .../TenantVisibilityRoleRuleRepository.cs | 58 - .../App/Persistence/TakeoutAppDbContext.cs | 1556 ---- .../TakeoutAppDesignTimeDbContextFactory.cs | 35 - .../App/Repositories/EfDeliveryRepository.cs | 117 - .../App/Repositories/EfInventoryRepository.cs | 145 - .../EfMerchantCategoryRepository.cs | 66 - .../App/Repositories/EfMerchantRepository.cs | 288 - .../App/Repositories/EfOrderRepository.cs | 170 - .../App/Repositories/EfPaymentRepository.cs | 110 - .../App/Repositories/EfProductRepository.cs | 511 -- .../Repositories/EfQuotaPackageRepository.cs | 166 - .../Repositories/EfStatisticsRepository.cs | 116 - .../App/Repositories/EfStoreRepository.cs | 645 -- .../Repositories/EfSubscriptionRepository.cs | 362 - .../EfTenantAnnouncementReadRepository.cs | 68 - .../EfTenantAnnouncementRepository.cs | 167 - .../EfTenantNotificationRepository.cs | 94 - .../Repositories/EfTenantPackageRepository.cs | 89 - .../EfTenantQuotaUsageHistoryRepository.cs | 24 - .../EfTenantQuotaUsageRepository.cs | 50 - .../App/Repositories/EfTenantRepository.cs | 356 - .../App/Services/BillingDomainService.cs | 233 - .../App/Services/BillingExportService.cs | 203 - .../App/Services/DeliveryZoneService.cs | 375 - .../App/Services/GeoJsonValidationService.cs | 221 - .../App/Services/MerchantExportService.cs | 152 - .../Services/StoreFeeCalculationService.cs | 125 - .../App/Services/StoreSchedulerService.cs | 302 - .../BackgroundServices/AutoRenewalService.cs | 202 - .../RenewalReminderService.cs | 191 - .../SubscriptionExpiryCheckService.cs | 158 - .../DatabaseServiceCollectionExtensions.cs | 102 - .../Options/DatabaseDataSourceOptions.cs | 38 - .../Common/Options/DatabaseOptions.cs | 33 - .../Common/Persistence/AppDbContext.cs | 239 - .../Common/Persistence/DapperExecutor.cs | 80 - .../Persistence/DatabaseConnectionDetails.cs | 10 - .../Persistence/DatabaseConnectionFactory.cs | 120 - .../DesignTimeDbContextFactoryBase.cs | 178 - .../Persistence/IDatabaseConnectionFactory.cs | 17 - .../ModelBuilderCommentExtensions.cs | 146 - .../Common/Persistence/QueryFilterCombiner.cs | 23 - .../Persistence/TenantAwareDbContext.cs | 104 - .../Caching/CacheMetricsCollector.cs | 212 - .../Dictionary/Caching/CacheWarmupService.cs | 57 - .../Dictionary/Caching/HybridCacheService.cs | 229 - .../Dictionary/Caching/MemoryCacheService.cs | 82 - .../Dictionary/Caching/RedisCacheService.cs | 79 - .../DictionaryServiceCollectionExtensions.cs | 111 - .../ImportExport/CsvDictionaryParser.cs | 91 - .../ImportExport/JsonDictionaryParser.cs | 131 - .../Options/DictionaryCacheOptions.cs | 12 - .../Options/DictionaryCacheWarmupOptions.cs | 12 - .../Persistence/DictionaryDbContext.cs | 267 - .../DictionaryDesignTimeDbContextFactory.cs | 35 - .../CacheInvalidationLogRepository.cs | 59 - .../Repositories/DictionaryGroupRepository.cs | 173 - .../DictionaryImportLogRepository.cs | 26 - .../Repositories/DictionaryItemRepository.cs | 147 - .../DictionaryLabelOverrideRepository.cs | 111 - .../Repositories/EfDictionaryRepository.cs | 200 - .../EfSystemParameterRepository.cs | 79 - .../TenantDictionaryOverrideRepository.cs | 60 - .../Services/DistributedDictionaryCache.cs | 75 - .../Extensions/JwtAuthenticationExtensions.cs | 54 - .../Extensions/ServiceCollectionExtensions.cs | 119 - .../Options/AdminPasswordResetOptions.cs | 13 - .../Identity/Options/AdminSeedOptions.cs | 101 - .../Identity/Options/JwtOptions.cs | 40 - .../Identity/Options/LoginRateLimitOptions.cs | 21 - .../Options/RefreshTokenStoreOptions.cs | 12 - .../Identity/Options/WeChatMiniOptions.cs | 21 - .../Persistence/EfIdentityUserRepository.cs | 373 - .../Persistence/EfMiniUserRepository.cs | 70 - .../Persistence/EfPermissionRepository.cs | 162 - .../Persistence/EfRolePermissionRepository.cs | 92 - .../Identity/Persistence/EfRoleRepository.cs | 136 - .../Persistence/EfRoleTemplateRepository.cs | 193 - .../Persistence/EfUserRoleRepository.cs | 133 - .../Persistence/IdentityDataSeeder.cs | 326 - .../Identity/Persistence/IdentityDbContext.cs | 246 - .../IdentityDesignTimeDbContextFactory.cs | 35 - .../Identity/Repositories/EfMenuRepository.cs | 72 - .../Identity/Services/JwtTokenService.cs | 95 - .../RedisAdminPasswordResetTokenStore.cs | 66 - .../Services/RedisLoginRateLimiter.cs | 56 - .../Services/RedisRefreshTokenStore.cs | 77 - .../Identity/Services/WeChatAuthService.cs | 79 - .../IdentityUserOperationLogConsumer.cs | 72 - ...ionLogOutboxServiceCollectionExtensions.cs | 56 - .../Persistence/OperationLogInboxMessage.cs | 19 - .../Logs/Persistence/TakeoutLogsDbContext.cs | 143 - .../TakeoutLogsDesignTimeDbContextFactory.cs | 35 - .../IdentityOperationLogPublisher.cs | 27 - .../Repositories/EfOperationLogRepository.cs | 63 - ...251202005208_InitSnowflake_App.Designer.cs | 5799 ------------- .../20251202005208_InitSnowflake_App.cs | 2549 ------ ...8_AddTenantVerificationProfile.Designer.cs | 6673 --------------- ...1205113018_AddTenantVerificationProfile.cs | 544 -- ...0251211150000_AddTenantPackageSortOrder.cs | 50 - ...dTenantContactPhoneUniqueIndex.Designer.cs | 6684 --------------- ...135400_AddTenantContactPhoneUniqueIndex.cs | 28 - ...215023947_AddTenantReviewClaim.Designer.cs | 6753 --------------- .../20251215023947_AddTenantReviewClaim.cs | 59 - ...antPackagePublishAndVisibility.Designer.cs | 6772 --------------- ...10_AddTenantPackagePublishAndVisibility.cs | 107 - ...35_ChangeTenantPackageDefaults.Designer.cs | 6772 --------------- ...51215130235_ChangeTenantPackageDefaults.cs | 42 - ...ntPackageRecommendationAndTags.Designer.cs | 6783 --------------- ...4_AddTenantPackageRecommendationAndTags.cs | 42 - ...09_AddQuotaPackagesAndPayments.Designer.cs | 7101 ---------------- ...51217092209_AddQuotaPackagesAndPayments.cs | 164 - ...0046_UpdateTenantBillingSchema.Designer.cs | 7174 ---------------- ...0251217160046_UpdateTenantBillingSchema.cs | 237 - ...3_AddTenantQuotaUsageHistories.Designer.cs | 7252 ---------------- ...1218121053_AddTenantQuotaUsageHistories.cs | 60 - ...AnnouncementStatusAndPublisher.Designer.cs | 7298 ---------------- ...AddTenantAnnouncementStatusAndPublisher.cs | 146 - ..._AddTenantAnnouncementRowVersionTrigger.cs | 54 - ...29071911_AddMerchantManagement.Designer.cs | 7080 ---------------- .../20251229071911_AddMerchantManagement.cs | 244 - ...137_AddStoreManagementEntities.Designer.cs | 7391 ---------------- ...251231124137_AddStoreManagementEntities.cs | 319 - ...eStoreQualificationDateColumns.Designer.cs | 7391 ---------------- ...054_ChangeStoreQualificationDateColumns.cs | 63 - ...teStoreQualificationDateFields.Designer.cs | 7391 ---------------- ...5217_UpdateStoreQualificationDateFields.cs | 63 - ...dStoreHolidayForTemporaryHours.Designer.cs | 7416 ---------------- ...508_ExtendStoreHolidayForTemporaryHours.cs | 173 - ...260201090000_AddStoreFeeTieredPackaging.cs | 45 - ...05247_InitSnowflake_Dictionary.Designer.cs | 210 - ...20251202005247_InitSnowflake_Dictionary.cs | 105 - ...43204_AddSystemParametersTable.Designer.cs | 288 - ...20251202043204_AddSystemParametersTable.cs | 58 - ...0044727_UpdateDictionarySchema.Designer.cs | 471 -- .../20251230044727_UpdateDictionarySchema.cs | 255 - ...40335_AddCacheInvalidationLogs.Designer.cs | 544 -- ...20251230140335_AddCacheInvalidationLogs.cs | 54 - ...0170000_AddDictionaryRowVersionTriggers.cs | 77 - ...16_AddDictionaryLabelOverrides.Designer.cs | 633 -- ...51230232516_AddDictionaryLabelOverrides.cs | 76 - .../DictionaryDbContextModelSnapshot.cs | 630 -- ...2005226_InitSnowflake_Identity.Designer.cs | 189 - .../20251202005226_InitSnowflake_Identity.cs | 98 - .../20251202084523_AddRbacModel.Designer.cs | 429 - .../IdentityDb/20251202084523_AddRbacModel.cs | 189 - ...04070039_AddRoleTemplateTables.Designer.cs | 548 -- .../20251204070039_AddRoleTemplateTables.cs | 82 - ...204070108_AddRoleTemplateModel.Designer.cs | 548 -- .../20251204070108_AddRoleTemplateModel.cs | 22 - ...51205131436_AddMenuDefinitions.Designer.cs | 667 -- .../20251205131436_AddMenuDefinitions.cs | 62 - ...6_AddPermissionHierarchyFields.Designer.cs | 683 -- ...1206021946_AddPermissionHierarchyFields.cs | 67 - ...2230_FixIdentitySchemaMismatch.Designer.cs | 681 -- ...0251217092230_FixIdentitySchemaMismatch.cs | 66 - ...ddIdentityUserManagementFields.Designer.cs | 726 -- ...6174411_AddIdentityUserManagementFields.cs | 178 - ...251227004313_AddIdentityOutbox.Designer.cs | 847 -- .../20251227004313_AddIdentityOutbox.cs | 101 - .../IdentityDbContextModelSnapshot.cs | 844 -- .../20251226091835_InitLogsDb.Designer.cs | 335 - .../LogsDb/20251226091835_InitLogsDb.cs | 21 - ...7_AddOperationLogInboxMessages.Designer.cs | 358 - ...1227004337_AddOperationLogInboxMessages.cs | 43 - ...1940_AddMerchantManagementLogs.Designer.cs | 454 - ...0251229071940_AddMerchantManagementLogs.cs | 141 - .../TakeoutLogsDbContextModelSnapshot.cs | 451 - .../TakeoutAppDbContextModelSnapshot.cs | 7421 ----------------- .../Extensions/DictionaryModuleExtensions.cs | 22 - .../Abstractions/IMessagePublisher.cs | 12 - .../Abstractions/IMessageSubscriber.cs | 12 - .../MessagingServiceCollectionExtensions.cs | 41 - .../Options/RabbitMqOptions.cs | 55 - .../Serialization/JsonMessageSerializer.cs | 22 - .../Services/NoOpMessagePublisher.cs | 21 - .../Services/NoOpMessageSubscriber.cs | 25 - .../Services/RabbitMqConnectionFactory.cs | 30 - .../Services/RabbitMqMessagePublisher.cs | 79 - .../Services/RabbitMqMessageSubscriber.cs | 101 - .../Abstractions/IRecurringJobRegistrar.cs | 12 - .../SchedulerServiceCollectionExtensions.cs | 85 - .../RecurringJobHostedService.cs | 21 - .../Jobs/BillingOverdueProcessJob.cs | 32 - .../Jobs/BusinessStatusAutoSwitchJob.cs | 24 - .../Jobs/CouponExpireJob.cs | 18 - .../Jobs/LogCleanupJob.cs | 18 - .../Jobs/OrderTimeoutJob.cs | 18 - .../Jobs/QualificationExpiryCheckJob.cs | 24 - .../Jobs/SubscriptionAutoRenewalJob.cs | 70 - .../Jobs/SubscriptionExpiryCheckJob.cs | 70 - .../Jobs/SubscriptionRenewalReminderJob.cs | 70 - .../Options/BillingAutomationOptions.cs | 16 - .../Options/SchedulerOptions.cs | 31 - .../Options/SubscriptionAutomationOptions.cs | 46 - .../Services/RecurringJobRegistrar.cs | 59 - .../Abstractions/ISmsSender.cs | 19 - .../Abstractions/ISmsSenderResolver.cs | 12 - .../SmsServiceCollectionExtensions.cs | 33 - .../Models/SmsSendRequest.cs | 42 - .../Models/SmsSendResult.cs | 22 - .../Options/AliyunSmsOptions.cs | 36 - .../Options/SmsOptions.cs | 41 - .../Options/TencentSmsOptions.cs | 42 - .../Services/AliyunSmsSender.cs | 34 - .../Services/SmsSenderResolver.cs | 25 - .../Services/TencentSmsSender.cs | 140 - .../TakeoutSaaS.Module.Sms/SmsProviderKind.cs | 17 - .../Abstractions/IObjectStorageProvider.cs | 34 - .../Abstractions/IStorageProviderResolver.cs | 14 - .../StorageServiceCollectionExtensions.cs | 34 - .../Models/StorageDirectUploadRequest.cs | 34 - .../Models/StorageDirectUploadResult.cs | 32 - .../Models/StorageUploadRequest.cs | 61 - .../Models/StorageUploadResult.cs | 32 - .../Options/AliyunOssOptions.cs | 45 - .../Options/QiniuKodoOptions.cs | 50 - .../Options/StorageOptions.cs | 44 - .../Options/StorageSecurityOptions.cs | 48 - .../Options/TencentCosOptions.cs | 54 - .../Providers/AliyunOssStorageProvider.cs | 162 - .../Providers/QiniuKodoStorageProvider.cs | 52 - .../Providers/S3StorageProviderBase.cs | 243 - .../Providers/TencentCosStorageProvider.cs | 45 - .../Services/StorageProviderResolver.cs | 27 - .../StorageProviderKind.cs | 22 - 924 files changed, 7 insertions(+), 191722 deletions(-) delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/BillingMapping.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Commands/BatchUpdateStatusCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Commands/CancelBillingCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Commands/ConfirmPaymentCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Commands/CreateBillCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Commands/CreateBillingCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Commands/GenerateSubscriptionBillingCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Commands/ProcessOverdueBillingsCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Commands/RecordPaymentCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Commands/UpdateBillStatusCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Commands/UpdateBillingStatusCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Commands/VerifyPaymentCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillDetailDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillingDetailDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillingDtos.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillingExportDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillingLineItemDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillingListDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillingStatisticsDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillingTrendPointDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Dto/PaymentDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Dto/PaymentRecordDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Handlers/BatchUpdateStatusCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Handlers/CancelBillingCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Handlers/ConfirmPaymentCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Handlers/CreateBillCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Handlers/CreateBillingCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Handlers/ExportBillingsQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GenerateSubscriptionBillingCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetBillDetailQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetBillListQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetBillingDetailQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetBillingListQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetBillingPaymentsQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetBillingStatisticsQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetOverdueBillingsQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetTenantPaymentsQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Handlers/ProcessOverdueBillingsCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Handlers/RecordPaymentCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Handlers/UpdateBillStatusCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Handlers/UpdateBillingStatusCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Handlers/VerifyPaymentCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Queries/ExportBillingsQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetBillDetailQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetBillListQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetBillingDetailQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetBillingListQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetBillingPaymentsQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetBillingStatisticsQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetOverdueBillingsQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetTenantPaymentsQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Validators/ConfirmPaymentCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Validators/CreateBillingCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Validators/RecordPaymentCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Billings/Validators/UpdateBillingStatusCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Deliveries/Commands/CreateDeliveryOrderCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Deliveries/Commands/DeleteDeliveryOrderCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Deliveries/Commands/UpdateDeliveryOrderCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Deliveries/Dto/DeliveryEventDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Deliveries/Dto/DeliveryOrderDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Deliveries/Handlers/CreateDeliveryOrderCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Deliveries/Handlers/DeleteDeliveryOrderCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Deliveries/Handlers/GetDeliveryOrderByIdQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Deliveries/Handlers/SearchDeliveryOrdersQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Deliveries/Handlers/UpdateDeliveryOrderCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Deliveries/Queries/GetDeliveryOrderByIdQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Deliveries/Queries/SearchDeliveryOrdersQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Deliveries/Validators/CreateDeliveryOrderCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Deliveries/Validators/SearchDeliveryOrdersQueryValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Deliveries/Validators/UpdateDeliveryOrderCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Extensions/AppApplicationServiceCollectionExtensions.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Inventory/Commands/AdjustInventoryCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Inventory/Commands/DeductInventoryCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Inventory/Commands/LockInventoryCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Inventory/Commands/ReleaseExpiredInventoryLocksCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Inventory/Commands/ReleaseInventoryCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Inventory/Commands/UpsertInventoryBatchCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Inventory/Dto/InventoryBatchDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Inventory/Dto/InventoryItemDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/AdjustInventoryCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/DeductInventoryCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/GetInventoryBatchesQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/GetInventoryItemQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/LockInventoryCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/ReleaseExpiredInventoryLocksCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/ReleaseInventoryCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/UpsertInventoryBatchCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Inventory/InventoryMapping.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Inventory/Queries/GetInventoryBatchesQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Inventory/Queries/GetInventoryItemQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Inventory/Validators/AdjustInventoryCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Inventory/Validators/DeductInventoryCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Inventory/Validators/LockInventoryCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Inventory/Validators/ReleaseInventoryCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Inventory/Validators/UpsertInventoryBatchCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Commands/AddMerchantDocumentCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Commands/CreateMerchantCategoryCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Commands/CreateMerchantCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Commands/CreateMerchantContractCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Commands/DeleteMerchantCategoryCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Commands/DeleteMerchantCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Commands/ReorderMerchantCategoriesCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Commands/UpdateMerchantCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Commands/UpdateMerchantContractStatusCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/AddMerchantDocumentCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/CreateMerchantCategoryCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/CreateMerchantCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/CreateMerchantContractCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/DeleteMerchantCategoryCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/DeleteMerchantCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/ExportMerchantPdfQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantAuditHistoryQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantAuditLogsQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantByIdQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantCategoriesQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantChangeHistoryQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantContractsQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantDetailQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantDocumentsQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantListQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/ListMerchantCategoriesQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/ReorderMerchantCategoriesCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/SearchMerchantsQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/UpdateMerchantCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/UpdateMerchantContractStatusCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Queries/ExportMerchantPdfQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantAuditHistoryQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantAuditLogsQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantByIdQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantCategoriesQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantChangeHistoryQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantContractsQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantDetailQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantDocumentsQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantListQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Queries/ListMerchantCategoriesQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Queries/SearchMerchantsQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Validators/CreateMerchantCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Validators/SearchMerchantsQueryValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Merchants/Validators/UpdateMerchantCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Orders/Commands/CreateOrderCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Orders/Commands/DeleteOrderCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Orders/Commands/OrderItemRequest.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Orders/Commands/UpdateOrderCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Orders/Dto/OrderDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Orders/Dto/OrderItemDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Orders/Dto/OrderStatusHistoryDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Orders/Dto/RefundRequestDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Orders/Handlers/CreateOrderCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Orders/Handlers/DeleteOrderCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Orders/Handlers/GetOrderByIdQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Orders/Handlers/SearchOrdersQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Orders/Handlers/UpdateOrderCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Orders/Queries/GetOrderByIdQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Orders/Queries/SearchOrdersQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Orders/Validators/CreateOrderCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Orders/Validators/SearchOrdersQueryValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Orders/Validators/UpdateOrderCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Payments/Commands/CreatePaymentCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Payments/Commands/DeletePaymentCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Payments/Commands/UpdatePaymentCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Payments/Dto/PaymentDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Payments/Dto/PaymentRefundDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Payments/Handlers/CreatePaymentCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Payments/Handlers/DeletePaymentCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Payments/Handlers/GetPaymentByIdQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Payments/Handlers/SearchPaymentsQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Payments/Handlers/UpdatePaymentCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Payments/Queries/GetPaymentByIdQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Payments/Queries/SearchPaymentsQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Payments/Validators/CreatePaymentCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Payments/Validators/SearchPaymentsQueryValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Payments/Validators/UpdatePaymentCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Commands/CreateProductCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Commands/DeleteProductCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Commands/PublishProductCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Commands/ReplaceProductAddonsCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Commands/ReplaceProductAttributesCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Commands/ReplaceProductMediaCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Commands/ReplaceProductPricingRulesCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Commands/ReplaceProductSkusCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Commands/UnpublishProductCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Commands/UpdateProductCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductAddonGroupDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductAddonOptionDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductAttributeGroupDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductAttributeOptionDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductCategoryMenuDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductDetailDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductMediaAssetDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductPricingRuleDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductSkuDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Dto/StoreMenuDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Handlers/CreateProductCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Handlers/DeleteProductCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Handlers/GetProductByIdQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Handlers/GetProductDetailQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Handlers/GetStoreMenuQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Handlers/PublishProductCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Handlers/ReplaceProductAddonsCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Handlers/ReplaceProductAttributesCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Handlers/ReplaceProductMediaCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Handlers/ReplaceProductPricingRulesCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Handlers/ReplaceProductSkusCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Handlers/SearchProductsQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Handlers/UnpublishProductCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Handlers/UpdateProductCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/ProductMapping.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Queries/GetProductByIdQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Queries/GetProductDetailQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Queries/GetStoreMenuQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Queries/SearchProductsQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Validators/CreateProductCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Validators/PublishProductCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Validators/ReplaceProductAddonsCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Validators/ReplaceProductAttributesCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Validators/ReplaceProductMediaCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Validators/ReplaceProductPricingRulesCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Validators/ReplaceProductSkusCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Validators/SearchProductsQueryValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Validators/UnpublishProductCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Products/Validators/UpdateProductCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/QuotaPackages/Commands/CreateQuotaPackageCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/QuotaPackages/Commands/DeleteQuotaPackageCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/QuotaPackages/Commands/PurchaseQuotaPackageCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/QuotaPackages/Commands/UpdateQuotaPackageCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/QuotaPackages/Commands/UpdateQuotaPackageStatusCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/QuotaPackages/Dto/QuotaPackageDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/QuotaPackages/Dto/QuotaPackageListDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/QuotaPackages/Dto/TenantQuotaPurchaseDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/QuotaPackages/Dto/TenantQuotaUsageDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/CreateQuotaPackageCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/DeleteQuotaPackageCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/GetQuotaPackageListQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/GetTenantQuotaPurchasesQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/GetTenantQuotaUsageQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/PurchaseQuotaPackageCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/UpdateQuotaPackageCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/UpdateQuotaPackageStatusCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/QuotaPackages/Queries/GetQuotaPackageListQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/QuotaPackages/Queries/GetTenantQuotaPurchasesQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/QuotaPackages/Queries/GetTenantQuotaUsageQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Statistics/Dto/ExpiringSubscriptionDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Statistics/Dto/QuotaUsageRankingDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Statistics/Dto/RevenueStatisticsDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Statistics/Dto/SubscriptionOverviewDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Statistics/Handlers/GetExpiringSubscriptionsQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Statistics/Handlers/GetQuotaUsageRankingQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Statistics/Handlers/GetRevenueStatisticsQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Statistics/Handlers/GetSubscriptionOverviewQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Statistics/Queries/GetExpiringSubscriptionsQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Statistics/Queries/GetQuotaUsageRankingQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Statistics/Queries/GetRevenueStatisticsQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Statistics/Queries/GetSubscriptionOverviewQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/BatchUpdateBusinessHoursCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreBusinessHourCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreDeliveryZoneCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreEmployeeShiftCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreHolidayCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStorePickupSlotCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreQualificationCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreStaffCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreTableAreaCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreBusinessHourCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreDeliveryZoneCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreEmployeeShiftCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreHolidayCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStorePickupSlotCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreQualificationCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreStaffCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreTableAreaCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreTableCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/GenerateStoreTablesCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/SubmitStoreAuditCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/ToggleBusinessStatusCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreBusinessHourCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreDeliveryZoneCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreEmployeeShiftCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreFeeCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreHolidayCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStorePickupSlotCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreQualificationCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreStaffCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreTableAreaCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreTableCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpsertStorePickupSettingCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/BatchUpdateBusinessHoursCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CalculateStoreFeeQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CheckStoreDeliveryZoneQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CheckStoreQualificationsQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreBusinessHourCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreDeliveryZoneCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreEmployeeShiftCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreHolidayCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStorePickupSlotCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreQualificationCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreStaffCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreTableAreaCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreBusinessHourCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreDeliveryZoneCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreEmployeeShiftCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreHolidayCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStorePickupSlotCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreQualificationCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreStaffCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreTableAreaCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreTableCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ExportStoreTableQRCodesQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GenerateStoreTablesCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GetAvailablePickupSlotsQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GetStoreByIdQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GetStoreFeeQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GetStorePickupSettingQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GetStoreTableContextQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListExpiringStoreQualificationsQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreBusinessHoursQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreDeliveryZonesQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreEmployeeShiftsQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreHolidaysQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStorePickupSlotsQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreQualificationsQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreStaffQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreTableAreasQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreTablesQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/SearchStoresQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/SubmitStoreAuditCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ToggleBusinessStatusCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreBusinessHourCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreDeliveryZoneCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreEmployeeShiftCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreFeeCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreHolidayCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStorePickupSlotCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreQualificationCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreStaffCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreTableAreaCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreTableCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpsertStorePickupSettingCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Queries/CalculateStoreFeeQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Queries/CheckStoreDeliveryZoneQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Queries/CheckStoreQualificationsQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Queries/ExportStoreTableQRCodesQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Queries/GetAvailablePickupSlotsQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Queries/GetStoreByIdQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Queries/GetStoreFeeQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Queries/GetStorePickupSettingQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Queries/GetStoreTableContextQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListExpiringStoreQualificationsQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreBusinessHoursQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreDeliveryZonesQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreEmployeeShiftsQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreHolidaysQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStorePickupSlotsQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreQualificationsQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreStaffQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreTableAreasQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreTablesQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Queries/SearchStoresQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Services/GeoJsonValidationResult.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Services/IDeliveryZoneService.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Services/IGeoJsonValidationService.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Services/IStoreFeeCalculationService.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Services/IStoreSchedulerService.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/BatchUpdateBusinessHoursCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/BusinessHourValidators.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/CalculateStoreFeeQueryValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/CheckStoreDeliveryZoneQueryValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreBusinessHourCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreDeliveryZoneCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreEmployeeShiftCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreHolidayCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStorePickupSlotCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreQualificationCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreStaffCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreTableAreaCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/DeleteStorePickupSlotCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/DeleteStoreQualificationCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/GenerateStoreTablesCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/GetStoreTableContextQueryValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/SearchStoresQueryValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/SubmitStoreAuditCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/ToggleBusinessStatusCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreBusinessHourCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreDeliveryZoneCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreEmployeeShiftCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreFeeCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreHolidayCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStorePickupSlotCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreQualificationCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreStaffCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreTableAreaCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreTableCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpsertStorePickupSettingCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/BatchExtendSubscriptionsCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/BatchSendReminderCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/ChangeSubscriptionPlanCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/ExtendSubscriptionCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/ProcessAutoRenewalCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/ProcessRenewalRemindersCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/ProcessSubscriptionExpiryCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/UpdateSubscriptionCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/UpdateSubscriptionStatusCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Subscriptions/Dto/QuotaUsageDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Subscriptions/Dto/SubscriptionDetailDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Subscriptions/Dto/SubscriptionHistoryDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Subscriptions/Dto/SubscriptionListDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/BatchExtendSubscriptionsCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/BatchSendReminderCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/ChangeSubscriptionPlanCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/ExtendSubscriptionCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/GetSubscriptionDetailQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/GetSubscriptionListQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/ProcessAutoRenewalCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/ProcessRenewalRemindersCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/ProcessSubscriptionExpiryCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/UpdateSubscriptionCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/UpdateSubscriptionStatusCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Subscriptions/Queries/GetSubscriptionDetailQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Subscriptions/Queries/GetSubscriptionListQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/SystemParameters/Commands/CreateSystemParameterCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/SystemParameters/Commands/DeleteSystemParameterCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/SystemParameters/Commands/UpdateSystemParameterCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/SystemParameters/Dto/SystemParameterDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/CreateSystemParameterCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/DeleteSystemParameterCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/GetSystemParameterByIdQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/SearchSystemParametersQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/UpdateSystemParameterCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/SystemParameters/Queries/GetSystemParameterByIdQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/SystemParameters/Queries/SearchSystemParametersQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/SystemParameters/Validators/CreateSystemParameterCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/SystemParameters/Validators/SearchSystemParametersQueryValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/SystemParameters/Validators/UpdateSystemParameterCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Commands/CheckTenantQuotaCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Commands/CreateTenantAnnouncementCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Commands/DeleteTenantAnnouncementCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Commands/MarkAnnouncementAsReadCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Commands/MarkTenantNotificationReadCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Commands/PublishAnnouncementCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Commands/RevokeAnnouncementCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Commands/SelfRegisterTenantCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Commands/SubmitTenantVerificationCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Commands/UpdateTenantAnnouncementCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Commands/UpdateTenantCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Dto/QuotaCheckResultDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Dto/QuotaUsageHistoryDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Dto/SelfRegisterResultDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantAnnouncementDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantBillingDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantNotificationDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantPackageDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantProgressDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantVerificationDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/CheckTenantQuotaCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/CreateTenantAnnouncementCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/DeleteTenantAnnouncementCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetAnnouncementByIdQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetPublicTenantPackagesQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetTenantBillQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetTenantPackageByIdQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetTenantProgressQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetTenantQuotaUsageHistoryQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetTenantsAnnouncementsQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetUnreadAnnouncementsQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/MarkAnnouncementAsReadCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/MarkTenantNotificationReadCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/PublishAnnouncementCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/RevokeAnnouncementCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/SearchTenantBillsQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/SearchTenantNotificationsQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/SelfRegisterTenantCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/SubmitTenantVerificationCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/UpdateTenantAnnouncementCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/UpdateTenantCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetAnnouncementByIdQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetPublicTenantPackagesQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetTenantBillQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetTenantPackageByIdQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetTenantProgressQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetTenantQuotaUsageHistoryQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetTenantsAnnouncementsQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetUnreadAnnouncementsQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Queries/SearchTenantBillsQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Queries/SearchTenantNotificationsQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Targeting/AnnouncementTargetContextFactory.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Targeting/TargetTypeFilter.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Targeting/TenantAnnouncementTargetTypePolicy.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/TenantMapping.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Validators/CreateAnnouncementCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Validators/GetTenantQuotaUsageHistoryQueryValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Validators/PublishAnnouncementCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Validators/RevokeAnnouncementCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Validators/SelfRegisterTenantCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/App/Tenants/Validators/UpdateAnnouncementCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Abstractions/ICsvDictionaryParser.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Abstractions/IDictionaryAppService.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Abstractions/IDictionaryCache.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Abstractions/IDictionaryHybridCache.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Abstractions/IJsonDictionaryParser.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Contracts/CreateDictionaryGroupRequest.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Contracts/CreateDictionaryItemRequest.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Contracts/DictionaryBatchQueryRequest.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Contracts/DictionaryGroupQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Contracts/DictionaryImportRequest.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Contracts/DictionaryOverrideHiddenItemsRequest.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Contracts/DictionaryOverrideSortOrderRequest.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Contracts/UpdateDictionaryGroupRequest.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Contracts/UpdateDictionaryItemRequest.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Extensions/DictionaryServiceCollectionExtensions.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Models/DictionaryGroupDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Models/DictionaryImportResultDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Models/DictionaryImportRow.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Models/DictionaryItemDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Models/LabelOverrideDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Models/OverrideConfigDto.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryAppService.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryCacheKeys.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryCommandService.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryImportExportService.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryLabelOverrideService.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryMapper.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryMergeService.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryOverrideService.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryQueryService.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryValueConverter.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Validators/CreateDictionaryGroupValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Validators/I18nValueValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Validators/UpdateDictionaryItemValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Abstractions/IAdminPasswordResetTokenStore.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Abstractions/IIdentityOperationLogPublisher.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Abstractions/ILoginRateLimiter.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Abstractions/IMiniAuthService.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Abstractions/IWeChatAuthService.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/AssignUserRolesCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/BatchIdentityUserOperationCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/BindRolePermissionsCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/ChangeIdentityUserStatusCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/CloneRoleTemplateCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/CopyRoleTemplateCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/CreateIdentityUserCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/CreateMenuCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/CreatePermissionCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/CreateRoleCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/CreateRoleTemplateCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/DeleteIdentityUserCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/DeleteMenuCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/DeletePermissionCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/DeleteRoleCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/DeleteRoleTemplateCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/InitializeRoleTemplatesCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/ResetAdminPasswordByTokenCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/ResetIdentityUserPasswordCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/RestoreIdentityUserCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/UpdateIdentityUserCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/UpdateMenuCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/UpdatePermissionCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/UpdateRoleCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/UpdateRoleTemplateCommand.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Events/IdentityUserOperationLogMessage.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Extensions/IdentityServiceCollectionExtensions.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/AssignUserRolesCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/BatchIdentityUserOperationCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/BindRolePermissionsCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/ChangeIdentityUserStatusCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/CloneRoleTemplateCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/CopyRoleTemplateCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/CreateIdentityUserCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/CreateMenuCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/CreatePermissionCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/CreateRoleCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/CreateRoleTemplateCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteIdentityUserCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteMenuCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/DeletePermissionCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteRoleCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteRoleTemplateCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/GetIdentityUserDetailQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/GetRoleTemplateQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/GetUserPermissionsQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/InitializeRoleTemplatesCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/ListMenusQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/ListRoleTemplatesQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/MenuDetailQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/MenuMapper.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/PermissionTreeQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/ResetAdminPasswordByTokenCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/ResetIdentityUserPasswordCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/RestoreIdentityUserCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/RoleDetailQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/RoleTemplatePermissionsQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/SearchIdentityUsersQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/SearchPermissionsQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/SearchRolesQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/SearchUserPermissionsQueryHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/TemplateMapper.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateIdentityUserCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateMenuCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdatePermissionCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateRoleCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateRoleTemplateCommandHandler.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/MenuPolicy.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Models/IdentityUserBatchOperation.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/PermissionPolicy.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Queries/GetIdentityUserDetailQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Queries/GetRoleTemplateQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Queries/GetUserPermissionsQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Queries/ListMenusQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Queries/ListRoleTemplatesQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Queries/MenuDetailQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Queries/PermissionTreeQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Queries/RoleDetailQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Queries/RoleTemplatePermissionsQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Queries/SearchIdentityUsersQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Queries/SearchPermissionsQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Queries/SearchRolesQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Queries/SearchUserPermissionsQuery.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Services/MiniAuthService.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Validators/BatchIdentityUserOperationCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Validators/CreateIdentityUserCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Validators/SearchIdentityUsersQueryValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Identity/Validators/UpdateIdentityUserCommandValidator.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Messaging/Abstractions/IEventPublisher.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Messaging/EventRoutingKeys.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Messaging/Events/OrderCreatedEvent.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Messaging/Events/PaymentSucceededEvent.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Messaging/Extensions/MessagingServiceCollectionExtensions.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Messaging/Services/EventPublisher.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Sms/Abstractions/IVerificationCodeService.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Sms/Contracts/SendVerificationCodeRequest.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Sms/Contracts/SendVerificationCodeResponse.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Sms/Contracts/VerifyVerificationCodeRequest.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Sms/Extensions/SmsServiceCollectionExtensions.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Sms/Options/VerificationCodeOptions.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Sms/Services/VerificationCodeService.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Storage/Abstractions/IFileStorageService.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Storage/Contracts/DirectUploadRequest.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Storage/Contracts/DirectUploadResponse.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Storage/Contracts/FileUploadResponse.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Storage/Contracts/UploadFileRequest.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Storage/Enums/UploadFileType.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Storage/Extensions/StorageServiceCollectionExtensions.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Storage/Extensions/UploadFileTypeParser.cs delete mode 100644 src/Application/TakeoutSaaS.Application/Storage/Services/FileStorageService.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Deliveries/Repositories/IDeliveryRepository.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/ICacheInvalidationLogRepository.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/IDictionaryGroupRepository.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/IDictionaryImportLogRepository.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/IDictionaryItemRepository.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/IDictionaryLabelOverrideRepository.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/IDictionaryRepository.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/ITenantDictionaryOverrideRepository.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Dictionary/ValueObjects/I18nValue.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Identity/Repositories/IMiniUserRepository.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Identity/Repositories/IRoleTemplateRepository.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Inventory/Repositories/IInventoryRepository.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Merchants/Repositories/IMerchantCategoryRepository.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Merchants/Services/IMerchantExportService.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Orders/Repositories/IOrderRepository.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Payments/Repositories/IPaymentRepository.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Products/Repositories/IProductRepository.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Stores/Events/StoreApprovedEvent.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Stores/Events/StoreForceClosedEvent.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Stores/Events/StoreRejectedEvent.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Stores/Events/StoreSubmittedEvent.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/SystemParameters/Repositories/ISystemParameterRepository.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Tenants/Enums/BillingExportFormat.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Tenants/Events/AnnouncementPublished.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Tenants/Events/AnnouncementRevoked.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/IQuotaPackageRepository.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/IStatisticsRepository.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ISubscriptionRepository.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ITenantAnnouncementReadRepository.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ITenantAnnouncementRepository.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ITenantQuotaUsageHistoryRepository.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Tenants/Services/IBillingDomainService.cs delete mode 100644 src/Domain/TakeoutSaaS.Domain/Tenants/Services/IBillingExportService.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Extensions/AppServiceCollectionExtensions.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Options/AppSeedOptions.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Options/DictionarySeedGroupOptions.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Options/DictionarySeedItemOptions.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Options/SystemParameterSeedOptions.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Options/TenantSeedOptions.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/AppDataSeeder.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/Configurations/TenantBillingStatementConfiguration.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/Configurations/TenantPaymentConfiguration.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/Repositories/TenantBillingRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/Repositories/TenantPaymentRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/Repositories/TenantVisibilityRoleRuleRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/TakeoutAppDbContext.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/TakeoutAppDesignTimeDbContextFactory.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfDeliveryRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfInventoryRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfMerchantCategoryRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfMerchantRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfOrderRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfPaymentRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfProductRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfQuotaPackageRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfStatisticsRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfStoreRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfSubscriptionRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantAnnouncementReadRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantAnnouncementRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantNotificationRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantPackageRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantQuotaUsageHistoryRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantQuotaUsageRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Services/BillingDomainService.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Services/BillingExportService.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Services/DeliveryZoneService.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Services/GeoJsonValidationService.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Services/MerchantExportService.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Services/StoreFeeCalculationService.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/App/Services/StoreSchedulerService.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/BackgroundServices/AutoRenewalService.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/BackgroundServices/RenewalReminderService.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/BackgroundServices/SubscriptionExpiryCheckService.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Extensions/DatabaseServiceCollectionExtensions.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Options/DatabaseDataSourceOptions.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Options/DatabaseOptions.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/AppDbContext.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/DapperExecutor.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/DatabaseConnectionDetails.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/DatabaseConnectionFactory.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/DesignTime/DesignTimeDbContextFactoryBase.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/IDatabaseConnectionFactory.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/ModelBuilderCommentExtensions.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/QueryFilterCombiner.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/TenantAwareDbContext.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Caching/CacheMetricsCollector.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Caching/CacheWarmupService.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Caching/HybridCacheService.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Caching/MemoryCacheService.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Caching/RedisCacheService.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Extensions/DictionaryServiceCollectionExtensions.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/ImportExport/CsvDictionaryParser.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/ImportExport/JsonDictionaryParser.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Options/DictionaryCacheOptions.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Options/DictionaryCacheWarmupOptions.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Persistence/DictionaryDbContext.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Persistence/DictionaryDesignTimeDbContextFactory.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/CacheInvalidationLogRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/DictionaryGroupRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/DictionaryImportLogRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/DictionaryItemRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/DictionaryLabelOverrideRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/EfDictionaryRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/EfSystemParameterRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/TenantDictionaryOverrideRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Services/DistributedDictionaryCache.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Extensions/JwtAuthenticationExtensions.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Extensions/ServiceCollectionExtensions.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Options/AdminPasswordResetOptions.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Options/AdminSeedOptions.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Options/JwtOptions.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Options/LoginRateLimitOptions.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Options/RefreshTokenStoreOptions.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Options/WeChatMiniOptions.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfIdentityUserRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfMiniUserRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfPermissionRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfRolePermissionRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfRoleRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfRoleTemplateRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfUserRoleRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/IdentityDataSeeder.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/IdentityDbContext.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/IdentityDesignTimeDbContextFactory.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Repositories/EfMenuRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Services/JwtTokenService.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Services/RedisAdminPasswordResetTokenStore.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Services/RedisLoginRateLimiter.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Services/RedisRefreshTokenStore.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Services/WeChatAuthService.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Consumers/IdentityUserOperationLogConsumer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Extensions/OperationLogOutboxServiceCollectionExtensions.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Persistence/OperationLogInboxMessage.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Persistence/TakeoutLogsDbContext.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Persistence/TakeoutLogsDesignTimeDbContextFactory.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Publishers/IdentityOperationLogPublisher.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Repositories/EfOperationLogRepository.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251202005208_InitSnowflake_App.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251202005208_InitSnowflake_App.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251205113018_AddTenantVerificationProfile.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251205113018_AddTenantVerificationProfile.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251211150000_AddTenantPackageSortOrder.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251212135400_AddTenantContactPhoneUniqueIndex.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251212135400_AddTenantContactPhoneUniqueIndex.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215023947_AddTenantReviewClaim.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215023947_AddTenantReviewClaim.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215092810_AddTenantPackagePublishAndVisibility.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215092810_AddTenantPackagePublishAndVisibility.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215130235_ChangeTenantPackageDefaults.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215130235_ChangeTenantPackageDefaults.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215143054_AddTenantPackageRecommendationAndTags.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215143054_AddTenantPackageRecommendationAndTags.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251217092209_AddQuotaPackagesAndPayments.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251217092209_AddQuotaPackagesAndPayments.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251217160046_UpdateTenantBillingSchema.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251217160046_UpdateTenantBillingSchema.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251218121053_AddTenantQuotaUsageHistories.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251218121053_AddTenantQuotaUsageHistories.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251220160000_AddTenantAnnouncementStatusAndPublisher.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251220160000_AddTenantAnnouncementStatusAndPublisher.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251225090000_AddTenantAnnouncementRowVersionTrigger.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251229071911_AddMerchantManagement.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251229071911_AddMerchantManagement.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251231124137_AddStoreManagementEntities.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251231124137_AddStoreManagementEntities.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20260120045054_ChangeStoreQualificationDateColumns.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20260120045054_ChangeStoreQualificationDateColumns.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20260120045217_UpdateStoreQualificationDateFields.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20260120045217_UpdateStoreQualificationDateFields.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20260120090508_ExtendStoreHolidayForTemporaryHours.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20260120090508_ExtendStoreHolidayForTemporaryHours.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20260201090000_AddStoreFeeTieredPackaging.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251202005247_InitSnowflake_Dictionary.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251202005247_InitSnowflake_Dictionary.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251202043204_AddSystemParametersTable.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251202043204_AddSystemParametersTable.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251230044727_UpdateDictionarySchema.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251230044727_UpdateDictionarySchema.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251230140335_AddCacheInvalidationLogs.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251230140335_AddCacheInvalidationLogs.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251230170000_AddDictionaryRowVersionTriggers.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251230232516_AddDictionaryLabelOverrides.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251230232516_AddDictionaryLabelOverrides.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/DictionaryDbContextModelSnapshot.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251202005226_InitSnowflake_Identity.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251202005226_InitSnowflake_Identity.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251202084523_AddRbacModel.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251202084523_AddRbacModel.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251204070039_AddRoleTemplateTables.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251204070039_AddRoleTemplateTables.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251204070108_AddRoleTemplateModel.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251204070108_AddRoleTemplateModel.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251205131436_AddMenuDefinitions.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251205131436_AddMenuDefinitions.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251206021946_AddPermissionHierarchyFields.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251206021946_AddPermissionHierarchyFields.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251217092230_FixIdentitySchemaMismatch.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251217092230_FixIdentitySchemaMismatch.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251226174411_AddIdentityUserManagementFields.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251226174411_AddIdentityUserManagementFields.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251227004313_AddIdentityOutbox.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251227004313_AddIdentityOutbox.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/IdentityDbContextModelSnapshot.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/LogsDb/20251226091835_InitLogsDb.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/LogsDb/20251226091835_InitLogsDb.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/LogsDb/20251227004337_AddOperationLogInboxMessages.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/LogsDb/20251227004337_AddOperationLogInboxMessages.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/LogsDb/20251229071940_AddMerchantManagementLogs.Designer.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/LogsDb/20251229071940_AddMerchantManagementLogs.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/LogsDb/TakeoutLogsDbContextModelSnapshot.cs delete mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/TakeoutAppDbContextModelSnapshot.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Dictionary/Extensions/DictionaryModuleExtensions.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Messaging/Abstractions/IMessagePublisher.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Messaging/Abstractions/IMessageSubscriber.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Messaging/Extensions/MessagingServiceCollectionExtensions.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Messaging/Options/RabbitMqOptions.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Messaging/Serialization/JsonMessageSerializer.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Messaging/Services/NoOpMessagePublisher.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Messaging/Services/NoOpMessageSubscriber.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Messaging/Services/RabbitMqConnectionFactory.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Messaging/Services/RabbitMqMessagePublisher.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Messaging/Services/RabbitMqMessageSubscriber.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Scheduler/Abstractions/IRecurringJobRegistrar.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Scheduler/Extensions/SchedulerServiceCollectionExtensions.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Scheduler/HostedServices/RecurringJobHostedService.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/BillingOverdueProcessJob.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/BusinessStatusAutoSwitchJob.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/CouponExpireJob.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/LogCleanupJob.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/OrderTimeoutJob.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/QualificationExpiryCheckJob.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/SubscriptionAutoRenewalJob.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/SubscriptionExpiryCheckJob.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/SubscriptionRenewalReminderJob.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Scheduler/Options/BillingAutomationOptions.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Scheduler/Options/SchedulerOptions.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Scheduler/Options/SubscriptionAutomationOptions.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Scheduler/Services/RecurringJobRegistrar.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Sms/Abstractions/ISmsSender.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Sms/Abstractions/ISmsSenderResolver.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Sms/Extensions/SmsServiceCollectionExtensions.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Sms/Models/SmsSendRequest.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Sms/Models/SmsSendResult.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Sms/Options/AliyunSmsOptions.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Sms/Options/SmsOptions.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Sms/Options/TencentSmsOptions.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Sms/Services/AliyunSmsSender.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Sms/Services/SmsSenderResolver.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Sms/Services/TencentSmsSender.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Sms/SmsProviderKind.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Storage/Abstractions/IObjectStorageProvider.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Storage/Abstractions/IStorageProviderResolver.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Storage/Extensions/StorageServiceCollectionExtensions.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Storage/Models/StorageDirectUploadRequest.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Storage/Models/StorageDirectUploadResult.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Storage/Models/StorageUploadRequest.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Storage/Models/StorageUploadResult.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Storage/Options/AliyunOssOptions.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Storage/Options/QiniuKodoOptions.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Storage/Options/StorageOptions.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Storage/Options/StorageSecurityOptions.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Storage/Options/TencentCosOptions.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Storage/Providers/AliyunOssStorageProvider.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Storage/Providers/QiniuKodoStorageProvider.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Storage/Providers/S3StorageProviderBase.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Storage/Providers/TencentCosStorageProvider.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Storage/Services/StorageProviderResolver.cs delete mode 100644 src/Modules/TakeoutSaaS.Module.Storage/StorageProviderKind.cs diff --git a/src/Api/TakeoutSaaS.TenantApi/Program.cs b/src/Api/TakeoutSaaS.TenantApi/Program.cs index 9802d8d..61bebe3 100644 --- a/src/Api/TakeoutSaaS.TenantApi/Program.cs +++ b/src/Api/TakeoutSaaS.TenantApi/Program.cs @@ -4,23 +4,14 @@ using Microsoft.AspNetCore.Mvc; using TakeoutSaaS.Shared.Abstractions.Security; using TakeoutSaaS.Shared.Abstractions.Serialization; using TakeoutSaaS.Shared.Web.Filters; -using TakeoutSaaS.Shared.Web.Security; using Microsoft.AspNetCore.Cors.Infrastructure; using OpenTelemetry.Metrics; using OpenTelemetry.Resources; using OpenTelemetry.Trace; using Serilog; -using TakeoutSaaS.Application.App.Extensions; -using TakeoutSaaS.Application.Dictionary.Extensions; -using TakeoutSaaS.Application.Identity.Extensions; -using TakeoutSaaS.Application.Messaging.Extensions; -using TakeoutSaaS.Infrastructure.App.Extensions; -using TakeoutSaaS.Infrastructure.Dictionary.Extensions; -using TakeoutSaaS.Infrastructure.Identity.Extensions; using TakeoutSaaS.Module.Authorization.Extensions; -using TakeoutSaaS.Module.Messaging.Extensions; -using TakeoutSaaS.Module.Tenancy.Extensions; using TakeoutSaaS.Shared.Web.Extensions; +using TakeoutSaaS.Shared.Web.Security; using TakeoutSaaS.Shared.Web.Swagger; // 1. 创建构建器与日志模板 @@ -86,29 +77,11 @@ if (isDevelopment) } // 5. 注册鉴权授权与权限策略 -builder.Services.AddJwtAuthentication(builder.Configuration); builder.Services.AddAuthorization(); builder.Services.AddPermissionAuthorization(); builder.Services.AddHealthChecks(); -// 6. 注册应用层与基础设施(仅租户侧所需) -builder.Services.AddAppApplication(); -builder.Services.AddIdentityApplication(enableMiniSupport: false); -builder.Services.AddAppInfrastructure(builder.Configuration); -builder.Services.AddIdentityInfrastructure(builder.Configuration, enableMiniFeatures: false, enableAdminSeed: false); - -// 7. 注册多租户解析(依赖 ITenantRepository,需在 Infrastructure 之后) -builder.Services.AddTenantResolution(builder.Configuration); - -// 6. (空行后) 注册字典模块(系统参数、字典项、缓存等) -builder.Services.AddDictionaryApplication(); -builder.Services.AddDictionaryInfrastructure(builder.Configuration); - -// 6. (空行后) 注册消息发布能力(未配置 RabbitMQ 时自动降级为 NoOp 实现) -builder.Services.AddMessagingApplication(); -builder.Services.AddMessagingModule(builder.Configuration); - -// 7. 配置 OpenTelemetry 采集 +// 6. 配置 OpenTelemetry 采集 var otelSection = builder.Configuration.GetSection("Otel"); var otelEndpoint = otelSection.GetValue("Endpoint"); var useConsoleExporter = otelSection.GetValue("UseConsoleExporter") ?? builder.Environment.IsDevelopment(); @@ -160,7 +133,7 @@ builder.Services.AddOpenTelemetry() } }); -// 8. 配置 CORS +// 7. 配置 CORS var tenantOrigins = ResolveCorsOrigins(builder.Configuration, "Cors:Tenant"); builder.Services.AddCors(options => { @@ -170,23 +143,17 @@ builder.Services.AddCors(options => }); }); -// 9. 构建应用并配置中间件管道 +// 8. 构建应用并配置中间件管道 var app = builder.Build(); app.UseCors("TenantApiCors"); -// 1. (空行后) 先完成身份认证,确保租户解析优先使用 Token Claim -app.UseAuthentication(); - -// 2. (空行后) 解析并注入租户上下文(已认证请求不允许 Header 覆盖) -app.UseTenantResolution(); - -// 3. (空行后) 通用 Web Core 中间件(异常、ProblemDetails、日志等) +// 1. (空行后) 通用 Web Core 中间件(异常、ProblemDetails、日志等) app.UseSharedWebCore(); -// 4. (空行后) 执行授权 +// 2. (空行后) 执行授权 app.UseAuthorization(); -// 5. (空行后) 开发环境启用 Swagger +// 3. (空行后) 开发环境启用 Swagger if (app.Environment.IsDevelopment()) { app.UseSharedSwagger(); diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/BillingMapping.cs b/src/Application/TakeoutSaaS.Application/App/Billings/BillingMapping.cs deleted file mode 100644 index ccea256..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/BillingMapping.cs +++ /dev/null @@ -1,200 +0,0 @@ -using System.Text.Json; -using TakeoutSaaS.Application.App.Billings.Dto; -using TakeoutSaaS.Domain.Tenants.Entities; - -namespace TakeoutSaaS.Application.App.Billings; - -/// -/// 账单 DTO 映射助手。 -/// -internal static class BillingMapping -{ - /// - /// 将账单实体映射为账单 DTO(旧版)。 - /// - /// 账单实体。 - /// 租户名称。 - /// 账单 DTO。 - public static BillDto ToDto(this TenantBillingStatement bill, string? tenantName = null) - => new() - { - Id = bill.Id, - TenantId = bill.TenantId, - TenantName = tenantName, - StatementNo = bill.StatementNo, - PeriodStart = bill.PeriodStart, - PeriodEnd = bill.PeriodEnd, - AmountDue = bill.AmountDue, - AmountPaid = bill.AmountPaid, - Status = bill.Status, - DueDate = bill.DueDate, - CreatedAt = bill.CreatedAt - }; - - /// - /// 将账单实体映射为账单列表 DTO(新版)。 - /// - /// 账单实体。 - /// 租户名称。 - /// 账单列表 DTO。 - public static BillingListDto ToBillingListDto(this TenantBillingStatement billing, string? tenantName = null) - => new() - { - Id = billing.Id, - TenantId = billing.TenantId, - SubscriptionId = billing.SubscriptionId, - TenantName = tenantName ?? string.Empty, - StatementNo = billing.StatementNo, - BillingType = billing.BillingType, - Status = billing.Status, - PeriodStart = billing.PeriodStart, - PeriodEnd = billing.PeriodEnd, - AmountDue = billing.AmountDue, - AmountPaid = billing.AmountPaid, - DiscountAmount = billing.DiscountAmount, - TaxAmount = billing.TaxAmount, - TotalAmount = billing.CalculateTotalAmount(), - Currency = billing.Currency, - DueDate = billing.DueDate, - CreatedAt = billing.CreatedAt, - UpdatedAt = billing.UpdatedAt, - IsOverdue = billing.Status == TakeoutSaaS.Domain.Tenants.Enums.TenantBillingStatus.Overdue - || (billing.Status == TakeoutSaaS.Domain.Tenants.Enums.TenantBillingStatus.Pending && billing.DueDate < DateTime.UtcNow), - OverdueDays = (billing.Status is TakeoutSaaS.Domain.Tenants.Enums.TenantBillingStatus.Pending - or TakeoutSaaS.Domain.Tenants.Enums.TenantBillingStatus.Overdue) - && billing.DueDate < DateTime.UtcNow - ? (int)(DateTime.UtcNow - billing.DueDate).TotalDays - : 0 - }; - - /// - /// 将账单实体与支付记录映射为账单详情 DTO(旧版)。 - /// - /// 账单实体。 - /// 支付记录列表。 - /// 租户名称。 - /// 账单详情 DTO。 - public static BillDetailDto ToDetailDto( - this TenantBillingStatement bill, - List payments, - string? tenantName = null) - => new() - { - Id = bill.Id, - TenantId = bill.TenantId, - TenantName = tenantName, - StatementNo = bill.StatementNo, - PeriodStart = bill.PeriodStart, - PeriodEnd = bill.PeriodEnd, - AmountDue = bill.AmountDue, - AmountPaid = bill.AmountPaid, - Status = bill.Status, - DueDate = bill.DueDate, - LineItemsJson = bill.LineItemsJson, - CreatedAt = bill.CreatedAt, - Payments = payments.Select(p => p.ToDto()).ToList() - }; - - /// - /// 将账单实体与支付记录映射为账单详情 DTO(新版)。 - /// - /// 账单实体。 - /// 支付记录列表。 - /// 租户名称。 - /// 账单详情 DTO。 - public static BillingDetailDto ToBillingDetailDto( - this TenantBillingStatement billing, - List payments, - string? tenantName = null) - { - // 反序列化账单明细 - var lineItems = new List(); - if (!string.IsNullOrWhiteSpace(billing.LineItemsJson)) - { - try - { - lineItems = JsonSerializer.Deserialize>(billing.LineItemsJson) ?? []; - } - catch - { - lineItems = []; - } - } - - return new BillingDetailDto - { - Id = billing.Id, - TenantId = billing.TenantId, - TenantName = tenantName ?? string.Empty, - SubscriptionId = billing.SubscriptionId, - StatementNo = billing.StatementNo, - BillingType = billing.BillingType, - Status = billing.Status, - PeriodStart = billing.PeriodStart, - PeriodEnd = billing.PeriodEnd, - AmountDue = billing.AmountDue, - AmountPaid = billing.AmountPaid, - DiscountAmount = billing.DiscountAmount, - TaxAmount = billing.TaxAmount, - TotalAmount = billing.CalculateTotalAmount(), - Currency = billing.Currency, - DueDate = billing.DueDate, - ReminderSentAt = billing.ReminderSentAt, - OverdueNotifiedAt = billing.OverdueNotifiedAt, - LineItemsJson = billing.LineItemsJson, - LineItems = lineItems, - Payments = payments.Select(p => p.ToPaymentRecordDto()).ToList(), - Notes = billing.Notes, - CreatedAt = billing.CreatedAt, - CreatedBy = billing.CreatedBy, - UpdatedAt = billing.UpdatedAt, - UpdatedBy = billing.UpdatedBy - }; - } - - /// - /// 将支付记录实体映射为支付 DTO(旧版)。 - /// - /// 支付记录实体。 - /// 支付 DTO。 - public static PaymentDto ToDto(this TenantPayment payment) - => new() - { - Id = payment.Id, - BillingStatementId = payment.BillingStatementId, - Amount = payment.Amount, - Method = payment.Method, - Status = payment.Status, - TransactionNo = payment.TransactionNo, - ProofUrl = payment.ProofUrl, - PaidAt = payment.PaidAt, - Notes = payment.Notes, - CreatedAt = payment.CreatedAt - }; - - /// - /// 将支付记录实体映射为支付记录 DTO(新版)。 - /// - /// 支付记录实体。 - /// 支付记录 DTO。 - public static PaymentRecordDto ToPaymentRecordDto(this TenantPayment payment) - => new() - { - Id = payment.Id, - TenantId = payment.TenantId, - BillingId = payment.BillingStatementId, - Amount = payment.Amount, - Method = payment.Method, - Status = payment.Status, - TransactionNo = payment.TransactionNo, - ProofUrl = payment.ProofUrl, - IsVerified = payment.VerifiedAt.HasValue, - PaidAt = payment.PaidAt, - VerifiedBy = payment.VerifiedBy, - VerifiedAt = payment.VerifiedAt, - RefundReason = payment.RefundReason, - RefundedAt = payment.RefundedAt, - Notes = payment.Notes, - CreatedAt = payment.CreatedAt - }; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Commands/BatchUpdateStatusCommand.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Commands/BatchUpdateStatusCommand.cs deleted file mode 100644 index 054a9e4..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Commands/BatchUpdateStatusCommand.cs +++ /dev/null @@ -1,25 +0,0 @@ -using MediatR; -using TakeoutSaaS.Domain.Tenants.Enums; - -namespace TakeoutSaaS.Application.App.Billings.Commands; - -/// -/// 批量更新账单状态命令。 -/// -public sealed record BatchUpdateStatusCommand : IRequest -{ - /// - /// 账单 ID 列表(雪花算法)。 - /// - public long[] BillingIds { get; init; } = []; - - /// - /// 新状态。 - /// - public TenantBillingStatus NewStatus { get; init; } - - /// - /// 批量操作备注。 - /// - public string? Notes { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Commands/CancelBillingCommand.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Commands/CancelBillingCommand.cs deleted file mode 100644 index ed38f36..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Commands/CancelBillingCommand.cs +++ /dev/null @@ -1,19 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.App.Billings.Commands; - -/// -/// 取消账单命令。 -/// -public sealed record CancelBillingCommand : IRequest -{ - /// - /// 账单 ID(雪花算法)。 - /// - public long BillingId { get; init; } - - /// - /// 取消原因。 - /// - public string Reason { get; init; } = string.Empty; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Commands/ConfirmPaymentCommand.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Commands/ConfirmPaymentCommand.cs deleted file mode 100644 index db00c49..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Commands/ConfirmPaymentCommand.cs +++ /dev/null @@ -1,42 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Billings.Dto; -using TakeoutSaaS.Domain.Tenants.Enums; - -namespace TakeoutSaaS.Application.App.Billings.Commands; - -/// -/// 一键确认收款命令(记录支付 + 立即审核通过)。 -/// -public sealed record ConfirmPaymentCommand : IRequest -{ - /// - /// 账单 ID(雪花算法)。 - /// - public long BillingId { get; init; } - - /// - /// 支付金额。 - /// - public decimal Amount { get; init; } - - /// - /// 支付方式。 - /// - public TenantPaymentMethod Method { get; init; } - - /// - /// 交易号。 - /// - public string? TransactionNo { get; init; } - - /// - /// 支付凭证 URL。 - /// - public string? ProofUrl { get; init; } - - /// - /// 备注信息。 - /// - public string? Notes { get; init; } -} - diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Commands/CreateBillCommand.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Commands/CreateBillCommand.cs deleted file mode 100644 index d22ecde..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Commands/CreateBillCommand.cs +++ /dev/null @@ -1,30 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Billings.Dto; - -namespace TakeoutSaaS.Application.App.Billings.Commands; - -/// -/// 创建账单命令。 -/// -public sealed record CreateBillCommand : IRequest -{ - /// - /// 租户 ID(雪花算法)。 - /// - public long TenantId { get; init; } - - /// - /// 应付金额。 - /// - public decimal AmountDue { get; init; } - - /// - /// 到期日(UTC)。 - /// - public DateTime DueDate { get; init; } - - /// - /// 备注信息。 - /// - public string? Notes { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Commands/CreateBillingCommand.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Commands/CreateBillingCommand.cs deleted file mode 100644 index d4abe30..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Commands/CreateBillingCommand.cs +++ /dev/null @@ -1,41 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Billings.Dto; -using TakeoutSaaS.Domain.Tenants.Enums; - -namespace TakeoutSaaS.Application.App.Billings.Commands; - -/// -/// 创建账单命令。 -/// -public sealed record CreateBillingCommand : IRequest -{ - /// - /// 租户 ID(雪花算法)。 - /// - public long TenantId { get; init; } - - /// - /// 账单类型。 - /// - public BillingType BillingType { get; init; } - - /// - /// 应付金额。 - /// - public decimal AmountDue { get; init; } - - /// - /// 到期日(UTC)。 - /// - public DateTime DueDate { get; init; } - - /// - /// 账单明细列表。 - /// - public List LineItems { get; init; } = []; - - /// - /// 备注。 - /// - public string? Notes { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Commands/GenerateSubscriptionBillingCommand.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Commands/GenerateSubscriptionBillingCommand.cs deleted file mode 100644 index be76d6b..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Commands/GenerateSubscriptionBillingCommand.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Billings.Dto; - -namespace TakeoutSaaS.Application.App.Billings.Commands; - -/// -/// 生成订阅账单命令(自动化场景)。 -/// -public sealed record GenerateSubscriptionBillingCommand : IRequest -{ - /// - /// 订阅 ID(雪花算法)。 - /// - public long SubscriptionId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Commands/ProcessOverdueBillingsCommand.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Commands/ProcessOverdueBillingsCommand.cs deleted file mode 100644 index 11d9d23..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Commands/ProcessOverdueBillingsCommand.cs +++ /dev/null @@ -1,10 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.App.Billings.Commands; - -/// -/// 处理逾期账单命令(后台任务场景)。 -/// -public sealed record ProcessOverdueBillingsCommand : IRequest -{ -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Commands/RecordPaymentCommand.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Commands/RecordPaymentCommand.cs deleted file mode 100644 index 46f94e0..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Commands/RecordPaymentCommand.cs +++ /dev/null @@ -1,41 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Billings.Dto; -using TakeoutSaaS.Domain.Tenants.Enums; - -namespace TakeoutSaaS.Application.App.Billings.Commands; - -/// -/// 记录支付命令。 -/// -public sealed record RecordPaymentCommand : IRequest -{ - /// - /// 账单 ID(雪花算法)。 - /// - public long BillingId { get; init; } - - /// - /// 支付金额。 - /// - public decimal Amount { get; init; } - - /// - /// 支付方式。 - /// - public TenantPaymentMethod Method { get; init; } - - /// - /// 交易号。 - /// - public string? TransactionNo { get; init; } - - /// - /// 支付凭证 URL。 - /// - public string? ProofUrl { get; init; } - - /// - /// 备注信息。 - /// - public string? Notes { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Commands/UpdateBillStatusCommand.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Commands/UpdateBillStatusCommand.cs deleted file mode 100644 index fcbff76..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Commands/UpdateBillStatusCommand.cs +++ /dev/null @@ -1,26 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Billings.Dto; -using TakeoutSaaS.Domain.Tenants.Enums; - -namespace TakeoutSaaS.Application.App.Billings.Commands; - -/// -/// 更新账单状态命令。 -/// -public sealed record UpdateBillStatusCommand : IRequest -{ - /// - /// 账单 ID(雪花算法)。 - /// - public long BillId { get; init; } - - /// - /// 新状态。 - /// - public TenantBillingStatus Status { get; init; } - - /// - /// 备注信息。 - /// - public string? Notes { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Commands/UpdateBillingStatusCommand.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Commands/UpdateBillingStatusCommand.cs deleted file mode 100644 index d6abcff..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Commands/UpdateBillingStatusCommand.cs +++ /dev/null @@ -1,25 +0,0 @@ -using MediatR; -using TakeoutSaaS.Domain.Tenants.Enums; - -namespace TakeoutSaaS.Application.App.Billings.Commands; - -/// -/// 更新账单状态命令。 -/// -public sealed record UpdateBillingStatusCommand : IRequest -{ - /// - /// 账单 ID(雪花算法)。 - /// - public long BillingId { get; init; } - - /// - /// 新状态。 - /// - public TenantBillingStatus NewStatus { get; init; } - - /// - /// 备注。 - /// - public string? Notes { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Commands/VerifyPaymentCommand.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Commands/VerifyPaymentCommand.cs deleted file mode 100644 index b652acd..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Commands/VerifyPaymentCommand.cs +++ /dev/null @@ -1,28 +0,0 @@ -using MediatR; -using System.ComponentModel.DataAnnotations; -using TakeoutSaaS.Application.App.Billings.Dto; - -namespace TakeoutSaaS.Application.App.Billings.Commands; - -/// -/// 审核支付命令。 -/// -public sealed record VerifyPaymentCommand : IRequest -{ - /// - /// 支付记录 ID(雪花算法)。 - /// - [Required] - public long PaymentId { get; init; } - - /// - /// 是否通过审核。 - /// - public bool Approved { get; init; } - - /// - /// 审核备注(可选)。 - /// - [MaxLength(512)] - public string? Notes { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillDetailDto.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillDetailDto.cs deleted file mode 100644 index 36b6851..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillDetailDto.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Billings.Dto; - -/// -/// 账单详情 DTO。 -/// -public sealed record BillDetailDto -{ - /// - /// 账单 ID(雪花算法,序列化为字符串)。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 租户 ID(雪花算法,序列化为字符串)。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 租户名称。 - /// - public string? TenantName { get; init; } - - /// - /// 账单编号。 - /// - public string StatementNo { get; init; } = string.Empty; - - /// - /// 计费周期开始时间(UTC)。 - /// - public DateTime PeriodStart { get; init; } - - /// - /// 计费周期结束时间(UTC)。 - /// - public DateTime PeriodEnd { get; init; } - - /// - /// 应付金额。 - /// - public decimal AmountDue { get; init; } - - /// - /// 已付金额。 - /// - public decimal AmountPaid { get; init; } - - /// - /// 账单状态。 - /// - public TenantBillingStatus Status { get; init; } - - /// - /// 到期日(UTC)。 - /// - public DateTime DueDate { get; init; } - - /// - /// 账单明细 JSON。 - /// - public string? LineItemsJson { get; init; } - - /// - /// 创建时间(UTC)。 - /// - public DateTime CreatedAt { get; init; } - - /// - /// 支付记录列表。 - /// - public List Payments { get; init; } = new(); -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillDto.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillDto.cs deleted file mode 100644 index dfc76d1..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillDto.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Billings.Dto; - -/// -/// 账单 DTO。 -/// -public sealed record BillDto -{ - /// - /// 账单 ID(雪花算法,序列化为字符串)。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 租户 ID(雪花算法,序列化为字符串)。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 租户名称。 - /// - public string? TenantName { get; init; } - - /// - /// 账单编号。 - /// - public string StatementNo { get; init; } = string.Empty; - - /// - /// 计费周期开始时间(UTC)。 - /// - public DateTime PeriodStart { get; init; } - - /// - /// 计费周期结束时间(UTC)。 - /// - public DateTime PeriodEnd { get; init; } - - /// - /// 应付金额。 - /// - public decimal AmountDue { get; init; } - - /// - /// 已付金额。 - /// - public decimal AmountPaid { get; init; } - - /// - /// 账单状态。 - /// - public TenantBillingStatus Status { get; init; } - - /// - /// 到期日(UTC)。 - /// - public DateTime DueDate { get; init; } - - /// - /// 创建时间(UTC)。 - /// - public DateTime CreatedAt { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillingDetailDto.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillingDetailDto.cs deleted file mode 100644 index 9d92bd3..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillingDetailDto.cs +++ /dev/null @@ -1,146 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Billings.Dto; - -/// -/// 账单详情 DTO(租户端)。 -/// -public sealed record BillingDetailDto -{ - /// - /// 账单 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 租户 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 租户名称。 - /// - public string TenantName { get; init; } = string.Empty; - - /// - /// 账单编号。 - /// - public string StatementNo { get; init; } = string.Empty; - - /// - /// 计费周期开始时间(UTC)。 - /// - public DateTime PeriodStart { get; init; } - - /// - /// 计费周期结束时间(UTC)。 - /// - public DateTime PeriodEnd { get; init; } - - /// - /// 账单类型。 - /// - public BillingType BillingType { get; init; } - - /// - /// 账单状态。 - /// - public TenantBillingStatus Status { get; init; } - - /// - /// 应付金额。 - /// - public decimal AmountDue { get; init; } - - /// - /// 已支付金额。 - /// - public decimal AmountPaid { get; init; } - - /// - /// 折扣金额。 - /// - public decimal DiscountAmount { get; init; } - - /// - /// 税费金额。 - /// - public decimal TaxAmount { get; init; } - - /// - /// 总金额(应付金额 - 折扣 + 税费)。 - /// - public decimal TotalAmount { get; init; } - - /// - /// 币种。 - /// - public string Currency { get; init; } = "CNY"; - - /// - /// 到期日。 - /// - public DateTime DueDate { get; init; } - - /// - /// 订阅 ID(可选)。 - /// - [JsonConverter(typeof(NullableSnowflakeIdJsonConverter))] - public long? SubscriptionId { get; init; } - - /// - /// 账单明细 JSON(原始字符串)。 - /// - public string? LineItemsJson { get; init; } - - /// - /// 账单明细行项目。 - /// - public IReadOnlyList LineItems { get; init; } = []; - - /// - /// 支付记录。 - /// - public IReadOnlyList Payments { get; init; } = []; - - /// - /// 提醒发送时间。 - /// - public DateTime? ReminderSentAt { get; init; } - - /// - /// 逾期通知时间。 - /// - public DateTime? OverdueNotifiedAt { get; init; } - - /// - /// 备注。 - /// - public string? Notes { get; init; } - - /// - /// 创建时间。 - /// - public DateTime CreatedAt { get; init; } - - /// - /// 创建人 ID。 - /// - [JsonConverter(typeof(NullableSnowflakeIdJsonConverter))] - public long? CreatedBy { get; init; } - - /// - /// 更新时间。 - /// - public DateTime? UpdatedAt { get; init; } - - /// - /// 更新人 ID。 - /// - [JsonConverter(typeof(NullableSnowflakeIdJsonConverter))] - public long? UpdatedBy { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillingDtos.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillingDtos.cs deleted file mode 100644 index 9ad57bb..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillingDtos.cs +++ /dev/null @@ -1,545 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Billings.Dto.Legacy; - -/// -/// 账单列表 DTO(用于列表展示)。 -/// -public sealed record BillingListDto -{ - /// - /// 账单 ID(雪花算法,序列化为字符串)。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 租户 ID(雪花算法,序列化为字符串)。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 租户名称。 - /// - public string TenantName { get; init; } = string.Empty; - - /// - /// 关联订阅 ID(仅订阅/续费账单可能有值)。 - /// - [JsonConverter(typeof(NullableSnowflakeIdJsonConverter))] - public long? SubscriptionId { get; init; } - - /// - /// 账单编号。 - /// - public string StatementNo { get; init; } = string.Empty; - - /// - /// 账单类型。 - /// - public BillingType BillingType { get; init; } - - /// - /// 计费周期开始时间(UTC)。 - /// - public DateTime PeriodStart { get; init; } - - /// - /// 计费周期结束时间(UTC)。 - /// - public DateTime PeriodEnd { get; init; } - - /// - /// 应付金额。 - /// - public decimal AmountDue { get; init; } - - /// - /// 折扣金额。 - /// - public decimal DiscountAmount { get; init; } - - /// - /// 税费金额。 - /// - public decimal TaxAmount { get; init; } - - /// - /// 总金额(应付金额 - 折扣 + 税费)。 - /// - public decimal TotalAmount { get; init; } - - /// - /// 已付金额。 - /// - public decimal AmountPaid { get; init; } - - /// - /// 币种。 - /// - public string Currency { get; init; } = "CNY"; - - /// - /// 账单状态。 - /// - public TenantBillingStatus Status { get; init; } - - /// - /// 到期日(UTC)。 - /// - public DateTime DueDate { get; init; } - - /// - /// 是否已逾期(根据到期日与状态综合判断)。 - /// - public bool IsOverdue { get; init; } - - /// - /// 逾期天数(未逾期为 0)。 - /// - public int OverdueDays { get; init; } - - /// - /// 创建时间(UTC)。 - /// - public DateTime CreatedAt { get; init; } - - /// - /// 更新时间(UTC)。 - /// - public DateTime? UpdatedAt { get; init; } -} - -/// -/// 账单详情 DTO(含明细项)。 -/// -public sealed record BillingDetailDto -{ - /// - /// 账单 ID(雪花算法,序列化为字符串)。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 租户 ID(雪花算法,序列化为字符串)。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 租户名称。 - /// - public string TenantName { get; init; } = string.Empty; - - /// - /// 账单编号。 - /// - public string StatementNo { get; init; } = string.Empty; - - /// - /// 关联订阅 ID(仅订阅/续费账单可能有值)。 - /// - [JsonConverter(typeof(NullableSnowflakeIdJsonConverter))] - public long? SubscriptionId { get; init; } - - /// - /// 账单类型。 - /// - public BillingType BillingType { get; init; } - - /// - /// 计费周期开始时间(UTC)。 - /// - public DateTime PeriodStart { get; init; } - - /// - /// 计费周期结束时间(UTC)。 - /// - public DateTime PeriodEnd { get; init; } - - /// - /// 应付金额。 - /// - public decimal AmountDue { get; init; } - - /// - /// 折扣金额。 - /// - public decimal DiscountAmount { get; init; } - - /// - /// 税费金额。 - /// - public decimal TaxAmount { get; init; } - - /// - /// 总金额(应付金额 - 折扣 + 税费)。 - /// - public decimal TotalAmount { get; init; } - - /// - /// 已付金额。 - /// - public decimal AmountPaid { get; init; } - - /// - /// 币种。 - /// - public string Currency { get; init; } = "CNY"; - - /// - /// 账单状态。 - /// - public TenantBillingStatus Status { get; init; } - - /// - /// 到期日(UTC)。 - /// - public DateTime DueDate { get; init; } - - /// - /// 账单明细 JSON。 - /// - public string? LineItemsJson { get; init; } - - /// - /// 账单明细列表(从 JSON 反序列化)。 - /// - public IReadOnlyList LineItems { get; init; } = []; - - /// - /// 支付记录列表。 - /// - public IReadOnlyList Payments { get; init; } = []; - - /// - /// 备注信息。 - /// - public string? Notes { get; init; } - - /// - /// 创建时间(UTC)。 - /// - public DateTime CreatedAt { get; init; } - - /// - /// 更新时间(UTC)。 - /// - public DateTime? UpdatedAt { get; init; } -} - -/// -/// 账单明细项 DTO。 -/// -public sealed record BillingLineItemDto -{ - /// - /// 明细类型(如:套餐费、配额包费用、其他费用)。 - /// - public string ItemType { get; init; } = string.Empty; - - /// - /// 描述。 - /// - public string Description { get; init; } = string.Empty; - - /// - /// 数量。 - /// - public decimal Quantity { get; init; } - - /// - /// 单价。 - /// - public decimal UnitPrice { get; init; } - - /// - /// 金额(数量 × 单价)。 - /// - public decimal Amount { get; init; } - - /// - /// 折扣率(0-1)。 - /// - public decimal? DiscountRate { get; init; } -} - -/// -/// 支付记录 DTO。 -/// -public sealed record PaymentRecordDto -{ - /// - /// 支付记录 ID(雪花算法,序列化为字符串)。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 租户 ID(雪花算法,序列化为字符串)。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 账单 ID(雪花算法,序列化为字符串)。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long BillingId { get; init; } - - /// - /// 支付金额。 - /// - public decimal Amount { get; init; } - - /// - /// 支付方式。 - /// - public TenantPaymentMethod Method { get; init; } - - /// - /// 支付状态。 - /// - public TenantPaymentStatus Status { get; init; } - - /// - /// 支付流水号。 - /// - public string? TransactionNo { get; init; } - - /// - /// 支付凭证 URL。 - /// - public string? ProofUrl { get; init; } - - /// - /// 备注。 - /// - public string? Notes { get; init; } - - /// - /// 审核状态(待审核/已通过/已拒绝)。 - /// - public bool IsVerified { get; init; } - - /// - /// 审核人 ID(雪花算法,序列化为字符串)。 - /// - [JsonConverter(typeof(NullableSnowflakeIdJsonConverter))] - public long? VerifiedBy { get; init; } - - /// - /// 审核时间(UTC)。 - /// - public DateTime? VerifiedAt { get; init; } - - /// - /// 退款原因。 - /// - public string? RefundReason { get; init; } - - /// - /// 退款时间(UTC)。 - /// - public DateTime? RefundedAt { get; init; } - - /// - /// 支付时间(UTC)。 - /// - public DateTime? PaidAt { get; init; } - - /// - /// 创建时间(UTC)。 - /// - public DateTime CreatedAt { get; init; } -} - -/// -/// 账单统计 DTO。 -/// -public sealed record BillingStatisticsDto -{ - /// - /// 租户 ID(当前租户)。 - /// - [JsonConverter(typeof(NullableSnowflakeIdJsonConverter))] - public long? TenantId { get; init; } - - /// - /// 统计周期开始时间(UTC)。 - /// - public DateTime StartDate { get; init; } - - /// - /// 统计周期结束时间(UTC)。 - /// - public DateTime EndDate { get; init; } - - /// - /// 分组方式(Day/Week/Month)。 - /// - public string GroupBy { get; init; } = "Day"; - - /// - /// 总账单数量。 - /// - public int TotalCount { get; init; } - - /// - /// 待付款账单数量。 - /// - public int PendingCount { get; init; } - - /// - /// 已付款账单数量。 - /// - public int PaidCount { get; init; } - - /// - /// 逾期账单数量。 - /// - public int OverdueCount { get; init; } - - /// - /// 已取消账单数量。 - /// - public int CancelledCount { get; init; } - - /// - /// 总应收金额(账单原始应付)。 - /// - public decimal TotalAmountDue { get; init; } - - /// - /// 总实收金额。 - /// - public decimal TotalAmountPaid { get; init; } - - /// - /// 总未收金额(总金额 - 实收)。 - /// - public decimal TotalAmountUnpaid { get; init; } - - /// - /// 逾期未收金额。 - /// - public decimal TotalOverdueAmount { get; init; } - - /// - /// 分组统计:应收金额趋势(Key 为分组起始日期 yyyy-MM-dd)。 - /// - public Dictionary AmountDueTrend { get; init; } = []; - - /// - /// 分组统计:实收金额趋势(Key 为分组起始日期 yyyy-MM-dd)。 - /// - public Dictionary AmountPaidTrend { get; init; } = []; - - /// - /// 分组统计:账单数量趋势(Key 为分组起始日期 yyyy-MM-dd)。 - /// - public Dictionary CountTrend { get; init; } = []; -} - -/// -/// 账单导出 DTO。 -/// -public sealed record BillingExportDto -{ - /// - /// 账单 ID(雪花算法,序列化为字符串)。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 租户 ID(雪花算法,序列化为字符串)。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 租户名称。 - /// - public string TenantName { get; init; } = string.Empty; - - /// - /// 账单编号。 - /// - public string StatementNo { get; init; } = string.Empty; - - /// - /// 关联订阅 ID(仅订阅/续费账单可能有值)。 - /// - [JsonConverter(typeof(NullableSnowflakeIdJsonConverter))] - public long? SubscriptionId { get; init; } - - /// - /// 账单类型。 - /// - public BillingType BillingType { get; init; } - - /// - /// 计费周期开始时间(UTC)。 - /// - public DateTime PeriodStart { get; init; } - - /// - /// 计费周期结束时间(UTC)。 - /// - public DateTime PeriodEnd { get; init; } - - /// - /// 应付金额。 - /// - public decimal AmountDue { get; init; } - - /// - /// 折扣金额。 - /// - public decimal DiscountAmount { get; init; } - - /// - /// 税费金额。 - /// - public decimal TaxAmount { get; init; } - - /// - /// 总金额。 - /// - public decimal TotalAmount { get; init; } - - /// - /// 已付金额。 - /// - public decimal AmountPaid { get; init; } - - /// - /// 账单状态。 - /// - public TenantBillingStatus Status { get; init; } - - /// - /// 币种。 - /// - public string Currency { get; init; } = "CNY"; - - /// - /// 到期日(UTC)。 - /// - public DateTime DueDate { get; init; } - - /// - /// 备注信息。 - /// - public string? Notes { get; init; } - - /// - /// 账单明细列表。 - /// - public List LineItems { get; init; } = []; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillingExportDto.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillingExportDto.cs deleted file mode 100644 index 341d515..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillingExportDto.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Billings.Dto; - -/// -/// 账单导出 DTO。 -/// -public sealed record BillingExportDto -{ - /// - /// 账单 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 租户 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 租户名称。 - /// - public string TenantName { get; init; } = string.Empty; - - /// - /// 账单编号。 - /// - public string StatementNo { get; init; } = string.Empty; - - /// - /// 订阅 ID(可选)。 - /// - [JsonConverter(typeof(NullableSnowflakeIdJsonConverter))] - public long? SubscriptionId { get; init; } - - /// - /// 账单类型。 - /// - public BillingType BillingType { get; init; } - - /// - /// 账单状态。 - /// - public TenantBillingStatus Status { get; init; } - - /// - /// 计费周期开始时间(UTC)。 - /// - public DateTime PeriodStart { get; init; } - - /// - /// 计费周期结束时间(UTC)。 - /// - public DateTime PeriodEnd { get; init; } - - /// - /// 应付金额。 - /// - public decimal AmountDue { get; init; } - - /// - /// 折扣金额。 - /// - public decimal DiscountAmount { get; init; } - - /// - /// 税费金额。 - /// - public decimal TaxAmount { get; init; } - - /// - /// 总金额(应付金额 - 折扣 + 税费)。 - /// - public decimal TotalAmount { get; init; } - - /// - /// 已支付金额。 - /// - public decimal AmountPaid { get; init; } - - /// - /// 币种。 - /// - public string Currency { get; init; } = "CNY"; - - /// - /// 到期日(UTC)。 - /// - public DateTime DueDate { get; init; } - - /// - /// 备注。 - /// - public string? Notes { get; init; } - - /// - /// 账单明细。 - /// - public IReadOnlyList LineItems { get; init; } = []; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillingLineItemDto.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillingLineItemDto.cs deleted file mode 100644 index 8be6cca..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillingLineItemDto.cs +++ /dev/null @@ -1,37 +0,0 @@ -namespace TakeoutSaaS.Application.App.Billings.Dto; - -/// -/// 账单明细行项目 DTO。 -/// -public sealed record BillingLineItemDto -{ - /// - /// 明细类型(如:订阅费、配额包费用、其他费用)。 - /// - public string ItemType { get; init; } = string.Empty; - - /// - /// 描述。 - /// - public string Description { get; init; } = string.Empty; - - /// - /// 数量。 - /// - public decimal Quantity { get; init; } - - /// - /// 单价。 - /// - public decimal UnitPrice { get; init; } - - /// - /// 金额(数量 × 单价)。 - /// - public decimal Amount { get; init; } - - /// - /// 折扣率(0-1,可选)。 - /// - public decimal? DiscountRate { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillingListDto.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillingListDto.cs deleted file mode 100644 index 92e35b6..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillingListDto.cs +++ /dev/null @@ -1,114 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Billings.Dto; - -/// -/// 账单列表 DTO(租户端列表展示)。 -/// -public sealed record BillingListDto -{ - /// - /// 账单 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 租户 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 租户名称。 - /// - public string TenantName { get; init; } = string.Empty; - - /// - /// 订阅 ID(可选)。 - /// - [JsonConverter(typeof(NullableSnowflakeIdJsonConverter))] - public long? SubscriptionId { get; init; } - - /// - /// 账单编号。 - /// - public string StatementNo { get; init; } = string.Empty; - - /// - /// 计费周期开始时间(UTC)。 - /// - public DateTime PeriodStart { get; init; } - - /// - /// 计费周期结束时间(UTC)。 - /// - public DateTime PeriodEnd { get; init; } - - /// - /// 账单类型。 - /// - public BillingType BillingType { get; init; } - - /// - /// 账单状态。 - /// - public TenantBillingStatus Status { get; init; } - - /// - /// 应付金额。 - /// - public decimal AmountDue { get; init; } - - /// - /// 已支付金额。 - /// - public decimal AmountPaid { get; init; } - - /// - /// 折扣金额。 - /// - public decimal DiscountAmount { get; init; } - - /// - /// 税费金额。 - /// - public decimal TaxAmount { get; init; } - - /// - /// 总金额(应付金额 - 折扣 + 税费)。 - /// - public decimal TotalAmount { get; init; } - - /// - /// 币种。 - /// - public string Currency { get; init; } = "CNY"; - - /// - /// 到期日。 - /// - public DateTime DueDate { get; init; } - - /// - /// 创建时间。 - /// - public DateTime CreatedAt { get; init; } - - /// - /// 更新时间。 - /// - public DateTime? UpdatedAt { get; init; } - - /// - /// 是否逾期。 - /// - public bool IsOverdue { get; init; } - - /// - /// 逾期天数(未逾期为 0)。 - /// - public int OverdueDays { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillingStatisticsDto.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillingStatisticsDto.cs deleted file mode 100644 index 73b037b..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillingStatisticsDto.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Billings.Dto; - -/// -/// 账单统计数据 DTO。 -/// -public sealed record BillingStatisticsDto -{ - /// - /// 租户 ID(当前租户)。 - /// - [JsonConverter(typeof(NullableSnowflakeIdJsonConverter))] - public long? TenantId { get; init; } - - /// - /// 统计开始时间(UTC)。 - /// - public DateTime StartDate { get; init; } - - /// - /// 统计结束时间(UTC)。 - /// - public DateTime EndDate { get; init; } - - /// - /// 分组方式(Day/Week/Month)。 - /// - public string GroupBy { get; init; } = "Day"; - - /// - /// 总账单数量。 - /// - public int TotalCount { get; init; } - - /// - /// 待支付账单数量。 - /// - public int PendingCount { get; init; } - - /// - /// 已支付账单数量。 - /// - public int PaidCount { get; init; } - - /// - /// 逾期账单数量。 - /// - public int OverdueCount { get; init; } - - /// - /// 已取消账单数量。 - /// - public int CancelledCount { get; init; } - - /// - /// 总应收金额。 - /// - public decimal TotalAmountDue { get; init; } - - /// - /// 已收金额。 - /// - public decimal TotalAmountPaid { get; init; } - - /// - /// 未收金额。 - /// - public decimal TotalAmountUnpaid { get; init; } - - /// - /// 逾期金额。 - /// - public decimal TotalOverdueAmount { get; init; } - - /// - /// 应收金额趋势(Key 为日期桶字符串)。 - /// - public IReadOnlyDictionary AmountDueTrend { get; init; } = new Dictionary(); - - /// - /// 实收金额趋势(Key 为日期桶字符串)。 - /// - public IReadOnlyDictionary AmountPaidTrend { get; init; } = new Dictionary(); - - /// - /// 数量趋势(Key 为日期桶字符串)。 - /// - public IReadOnlyDictionary CountTrend { get; init; } = new Dictionary(); -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillingTrendPointDto.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillingTrendPointDto.cs deleted file mode 100644 index 68c8c9e..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Dto/BillingTrendPointDto.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace TakeoutSaaS.Application.App.Billings.Dto; - -/// -/// 账单趋势数据点 DTO。 -/// -public sealed record BillingTrendPointDto -{ - /// - /// 分组时间点(Day/Week/Month 对齐后的时间)。 - /// - public DateTime Period { get; init; } - - /// - /// 账单数量。 - /// - public int Count { get; init; } - - /// - /// 应收金额。 - /// - public decimal AmountDue { get; init; } - - /// - /// 实收金额。 - /// - public decimal AmountPaid { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Dto/PaymentDto.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Dto/PaymentDto.cs deleted file mode 100644 index 79f0921..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Dto/PaymentDto.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Billings.Dto; - -/// -/// 支付记录 DTO。 -/// -public sealed record PaymentDto -{ - /// - /// 支付记录 ID(雪花算法,序列化为字符串)。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 账单 ID(雪花算法,序列化为字符串)。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long BillingStatementId { get; init; } - - /// - /// 支付金额。 - /// - public decimal Amount { get; init; } - - /// - /// 支付方式。 - /// - public TenantPaymentMethod Method { get; init; } - - /// - /// 支付状态。 - /// - public TenantPaymentStatus Status { get; init; } - - /// - /// 交易号。 - /// - public string? TransactionNo { get; init; } - - /// - /// 支付凭证 URL。 - /// - public string? ProofUrl { get; init; } - - /// - /// 支付时间。 - /// - public DateTime? PaidAt { get; init; } - - /// - /// 备注信息。 - /// - public string? Notes { get; init; } - - /// - /// 创建时间(UTC)。 - /// - public DateTime CreatedAt { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Dto/PaymentRecordDto.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Dto/PaymentRecordDto.cs deleted file mode 100644 index 8e37c41..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Dto/PaymentRecordDto.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Billings.Dto; - -/// -/// 支付记录 DTO(租户端)。 -/// -public sealed record PaymentRecordDto -{ - /// - /// 支付记录 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 租户 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 关联的账单 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long BillingId { get; init; } - - /// - /// 支付金额。 - /// - public decimal Amount { get; init; } - - /// - /// 支付方式。 - /// - public TenantPaymentMethod Method { get; init; } - - /// - /// 支付状态。 - /// - public TenantPaymentStatus Status { get; init; } - - /// - /// 交易号。 - /// - public string? TransactionNo { get; init; } - - /// - /// 支付凭证 URL。 - /// - public string? ProofUrl { get; init; } - - /// - /// 支付时间。 - /// - public DateTime? PaidAt { get; init; } - - /// - /// 是否已审核。 - /// - public bool IsVerified { get; init; } - - /// - /// 审核人 ID。 - /// - [JsonConverter(typeof(NullableSnowflakeIdJsonConverter))] - public long? VerifiedBy { get; init; } - - /// - /// 审核时间。 - /// - public DateTime? VerifiedAt { get; init; } - - /// - /// 退款原因。 - /// - public string? RefundReason { get; init; } - - /// - /// 退款时间。 - /// - public DateTime? RefundedAt { get; init; } - - /// - /// 备注信息。 - /// - public string? Notes { get; init; } - - /// - /// 创建时间(UTC)。 - /// - public DateTime CreatedAt { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/BatchUpdateStatusCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/BatchUpdateStatusCommandHandler.cs deleted file mode 100644 index 84cd172..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/BatchUpdateStatusCommandHandler.cs +++ /dev/null @@ -1,110 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Billings.Commands; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Billings.Handlers; - -/// -/// 批量更新账单状态处理器。 -/// -public sealed class BatchUpdateStatusCommandHandler( - ITenantBillingRepository billingRepository, - ITenantContextAccessor tenantContextAccessor) - : IRequestHandler -{ - /// - /// 处理批量更新账单状态请求。 - /// - /// 批量更新状态命令。 - /// 取消标记。 - /// 成功更新的账单数量。 - public async Task Handle(BatchUpdateStatusCommand request, CancellationToken cancellationToken) - { - // 1. 参数验证 - if (request.BillingIds.Length == 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "账单 ID 列表不能为空"); - } - - // 2. 查询所有账单 - var billings = await billingRepository.GetByIdsAsync(request.BillingIds, cancellationToken); - if (billings.Count == 0) - { - throw new BusinessException(ErrorCodes.NotFound, "未找到任何匹配的账单"); - } - - // 3. 批量更新状态(逐租户上下文执行,避免跨租户写入) - var now = DateTime.UtcNow; - var currentTenantId = tenantContextAccessor.Current?.TenantId ?? 0; - if (currentTenantId != 0 && billings.Any(x => x.TenantId != currentTenantId)) - { - throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户批量更新账单状态"); - } - - var updatedTotal = 0; - var grouped = billings.GroupBy(x => x.TenantId).ToList(); - foreach (var group in grouped) - { - using (currentTenantId == 0 ? tenantContextAccessor.EnterTenantScope(group.Key, "billing:batch-update") : null) - { - var updatedCount = 0; - foreach (var billing in group) - { - // 业务规则检查:某些状态转换可能不允许 - if (!CanTransitionStatus(billing.Status, request.NewStatus)) - { - continue; - } - - billing.Status = request.NewStatus; - billing.UpdatedAt = now; - - if (!string.IsNullOrWhiteSpace(request.Notes)) - { - billing.Notes = string.IsNullOrWhiteSpace(billing.Notes) - ? $"[批量操作] {request.Notes}" - : $"{billing.Notes}\n[批量操作] {request.Notes}"; - } - - await billingRepository.UpdateAsync(billing, cancellationToken); - updatedCount++; - } - - if (updatedCount > 0) - { - await billingRepository.SaveChangesAsync(cancellationToken); - } - - updatedTotal += updatedCount; - } - } - - return updatedTotal; - } - - /// - /// 检查状态转换是否允许。 - /// - private static bool CanTransitionStatus( - TakeoutSaaS.Domain.Tenants.Enums.TenantBillingStatus currentStatus, - TakeoutSaaS.Domain.Tenants.Enums.TenantBillingStatus newStatus) - { - // 已支付的账单不能改为其他状态 - if (currentStatus == TakeoutSaaS.Domain.Tenants.Enums.TenantBillingStatus.Paid - && newStatus != TakeoutSaaS.Domain.Tenants.Enums.TenantBillingStatus.Paid) - { - return false; - } - - // 已取消的账单不能改为其他状态 - if (currentStatus == TakeoutSaaS.Domain.Tenants.Enums.TenantBillingStatus.Cancelled) - { - return false; - } - - return true; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/CancelBillingCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/CancelBillingCommandHandler.cs deleted file mode 100644 index c1a8da3..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/CancelBillingCommandHandler.cs +++ /dev/null @@ -1,36 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Billings.Commands; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; - -namespace TakeoutSaaS.Application.App.Billings.Handlers; - -/// -/// 取消账单命令处理器。 -/// -public sealed class CancelBillingCommandHandler( - ITenantBillingRepository billingRepository) - : IRequestHandler -{ - /// - public async Task Handle(CancelBillingCommand request, CancellationToken cancellationToken) - { - // 1. 查询账单 - var billing = await billingRepository.FindByIdAsync(request.BillingId, cancellationToken); - if (billing is null) - { - throw new BusinessException(ErrorCodes.NotFound, "账单不存在"); - } - - // 2. 取消账单(领域规则校验在实体方法内) - billing.Cancel(request.Reason); - - // 3. 持久化 - await billingRepository.UpdateAsync(billing, cancellationToken); - await billingRepository.SaveChangesAsync(cancellationToken); - - return Unit.Value; - } -} - diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/ConfirmPaymentCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/ConfirmPaymentCommandHandler.cs deleted file mode 100644 index 57a36d1..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/ConfirmPaymentCommandHandler.cs +++ /dev/null @@ -1,99 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Billings.Commands; -using TakeoutSaaS.Application.App.Billings.Dto; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Ids; -using TakeoutSaaS.Shared.Abstractions.Security; - -namespace TakeoutSaaS.Application.App.Billings.Handlers; - -/// -/// 一键确认收款处理器(记录支付 + 立即审核通过 + 同步更新账单已收金额/状态)。 -/// -public sealed class ConfirmPaymentCommandHandler( - ITenantBillingRepository billingRepository, - ITenantPaymentRepository paymentRepository, - IIdGenerator idGenerator, - ICurrentUserAccessor currentUserAccessor) - : IRequestHandler -{ - /// - public async Task Handle(ConfirmPaymentCommand request, CancellationToken cancellationToken) - { - // 1. 校验操作者身份(用于写入 VerifiedBy) - if (!currentUserAccessor.IsAuthenticated || currentUserAccessor.UserId <= 0) - { - throw new BusinessException(ErrorCodes.Unauthorized, "未登录或无效的操作者身份"); - } - - // 2. 查询账单 - var billing = await billingRepository.FindByIdAsync(request.BillingId, cancellationToken); - if (billing is null) - { - throw new BusinessException(ErrorCodes.NotFound, "账单不存在"); - } - - // 3. 业务规则检查 - if (billing.Status == TenantBillingStatus.Paid) - { - throw new BusinessException(ErrorCodes.BusinessError, "已支付账单不允许重复收款"); - } - - if (billing.Status == TenantBillingStatus.Cancelled) - { - throw new BusinessException(ErrorCodes.BusinessError, "已取消账单不允许收款"); - } - - // 4. 金额边界:不允许超过剩余应收(与前端校验保持一致) - var totalAmount = billing.CalculateTotalAmount(); - var remainingAmount = totalAmount - billing.AmountPaid; - if (request.Amount > remainingAmount) - { - throw new BusinessException(ErrorCodes.BadRequest, "支付金额不能超过剩余应收"); - } - - // 5. 幂等校验:交易号唯一 - if (!string.IsNullOrWhiteSpace(request.TransactionNo)) - { - var exists = await paymentRepository.GetByTransactionNoAsync(request.TransactionNo.Trim(), cancellationToken); - if (exists is not null) - { - throw new BusinessException(ErrorCodes.Conflict, "交易号已存在,疑似重复提交"); - } - } - - // 6. 构建支付记录并立即审核通过 - var now = DateTime.UtcNow; - var payment = new TenantPayment - { - Id = idGenerator.NextId(), - TenantId = billing.TenantId, - BillingStatementId = request.BillingId, - Amount = request.Amount, - Method = request.Method, - Status = TenantPaymentStatus.Pending, - TransactionNo = string.IsNullOrWhiteSpace(request.TransactionNo) ? null : request.TransactionNo.Trim(), - ProofUrl = request.ProofUrl, - PaidAt = now, - Notes = request.Notes - }; - - payment.Verify(currentUserAccessor.UserId); - - // 7. 同步更新账单已收金额/状态(支持分次收款) - billing.MarkAsPaid(payment.Amount, payment.TransactionNo ?? string.Empty); - - // 8. 持久化变更(同一 DbContext 下单次 SaveChanges 可提交两张表) - await paymentRepository.AddAsync(payment, cancellationToken); - await billingRepository.UpdateAsync(billing, cancellationToken); - await paymentRepository.SaveChangesAsync(cancellationToken); - - // 9. 返回 DTO - return payment.ToPaymentRecordDto(); - } -} - diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/CreateBillCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/CreateBillCommandHandler.cs deleted file mode 100644 index bbcf044..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/CreateBillCommandHandler.cs +++ /dev/null @@ -1,61 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Billings.Commands; -using TakeoutSaaS.Application.App.Billings.Dto; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Ids; - -namespace TakeoutSaaS.Application.App.Billings.Handlers; - -/// -/// 创建账单处理器。 -/// -public sealed class CreateBillCommandHandler( - ITenantBillingRepository billingRepository, - ITenantRepository tenantRepository, - IIdGenerator idGenerator) - : IRequestHandler -{ - /// - /// 处理创建账单请求。 - /// - /// 创建命令。 - /// 取消标记。 - /// 账单 DTO。 - public async Task Handle(CreateBillCommand request, CancellationToken cancellationToken) - { - // 1. 验证租户存在 - var tenant = await tenantRepository.FindByIdAsync(request.TenantId, cancellationToken); - if (tenant is null) - { - throw new BusinessException(ErrorCodes.NotFound, "租户不存在"); - } - - // 2. 生成账单编号 - var statementNo = $"BILL-{DateTime.UtcNow:yyyyMMdd}-{idGenerator.NextId()}"; - - // 3. 构建账单实体 - var bill = new TenantBillingStatement - { - TenantId = request.TenantId, - StatementNo = statementNo, - PeriodStart = DateTime.UtcNow, - PeriodEnd = DateTime.UtcNow, - AmountDue = request.AmountDue, - AmountPaid = 0, - Status = TenantBillingStatus.Pending, - DueDate = request.DueDate, - LineItemsJson = request.Notes - }; - - // 4. 持久化账单 - await billingRepository.AddAsync(bill, cancellationToken); - await billingRepository.SaveChangesAsync(cancellationToken); - - // 5. 返回 DTO - return bill.ToDto(tenant.Name); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/CreateBillingCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/CreateBillingCommandHandler.cs deleted file mode 100644 index 8c8727d..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/CreateBillingCommandHandler.cs +++ /dev/null @@ -1,65 +0,0 @@ -using MediatR; -using System.Text.Json; -using TakeoutSaaS.Application.App.Billings.Commands; -using TakeoutSaaS.Application.App.Billings.Dto; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Ids; - -namespace TakeoutSaaS.Application.App.Billings.Handlers; - -/// -/// 创建账单命令处理器。 -/// -public sealed class CreateBillingCommandHandler( - ITenantRepository tenantRepository, - ITenantBillingRepository billingRepository, - IIdGenerator idGenerator) - : IRequestHandler -{ - /// - public async Task Handle(CreateBillingCommand request, CancellationToken cancellationToken) - { - // 1. 校验租户存在 - var tenant = await tenantRepository.FindByIdAsync(request.TenantId, cancellationToken); - if (tenant is null) - { - throw new BusinessException(ErrorCodes.NotFound, "租户不存在"); - } - - // 2. 构建账单实体 - var now = DateTime.UtcNow; - var statementNo = $"BIL-{now:yyyyMMdd}-{idGenerator.NextId()}"; - var lineItemsJson = JsonSerializer.Serialize(request.LineItems); - - var billing = new TenantBillingStatement - { - TenantId = request.TenantId, - StatementNo = statementNo, - BillingType = request.BillingType, - SubscriptionId = null, - PeriodStart = now, - PeriodEnd = now, - AmountDue = request.AmountDue, - DiscountAmount = 0m, - TaxAmount = 0m, - AmountPaid = 0m, - Currency = "CNY", - Status = TenantBillingStatus.Pending, - DueDate = request.DueDate, - LineItemsJson = lineItemsJson, - Notes = request.Notes - }; - - // 3. 持久化账单 - await billingRepository.AddAsync(billing, cancellationToken); - await billingRepository.SaveChangesAsync(cancellationToken); - - // 4. 返回详情 DTO - return billing.ToBillingDetailDto([], tenant.Name); - } -} - diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/ExportBillingsQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/ExportBillingsQueryHandler.cs deleted file mode 100644 index 7731d80..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/ExportBillingsQueryHandler.cs +++ /dev/null @@ -1,44 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Billings.Queries; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Domain.Tenants.Services; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; - -namespace TakeoutSaaS.Application.App.Billings.Handlers; - -/// -/// 导出账单处理器。 -/// -public sealed class ExportBillingsQueryHandler( - ITenantBillingRepository billingRepository, - IBillingExportService exportService) - : IRequestHandler -{ - /// - public async Task Handle(ExportBillingsQuery request, CancellationToken cancellationToken) - { - // 1. 参数验证 - if (request.BillingIds.Length == 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "账单 ID 列表不能为空"); - } - - // 2. 查询账单数据 - var billings = await billingRepository.GetByIdsAsync(request.BillingIds, cancellationToken); - if (billings.Count == 0) - { - throw new BusinessException(ErrorCodes.NotFound, "未找到任何匹配的账单"); - } - - // 3. 根据格式导出 - var format = (request.Format ?? string.Empty).Trim().ToLowerInvariant(); - return format switch - { - "excel" or "xlsx" => await exportService.ExportToExcelAsync(billings, cancellationToken), - "pdf" => await exportService.ExportToPdfAsync(billings, cancellationToken), - "csv" => await exportService.ExportToCsvAsync(billings, cancellationToken), - _ => throw new BusinessException(ErrorCodes.BadRequest, $"不支持的导出格式: {request.Format}") - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GenerateSubscriptionBillingCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GenerateSubscriptionBillingCommandHandler.cs deleted file mode 100644 index d92b089..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GenerateSubscriptionBillingCommandHandler.cs +++ /dev/null @@ -1,102 +0,0 @@ -using MediatR; -using System.Text.Json; -using TakeoutSaaS.Application.App.Billings.Commands; -using TakeoutSaaS.Application.App.Billings.Dto; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Ids; - -namespace TakeoutSaaS.Application.App.Billings.Handlers; - -/// -/// 生成订阅账单命令处理器。 -/// -public sealed class GenerateSubscriptionBillingCommandHandler( - ISubscriptionRepository subscriptionRepository, - ITenantBillingRepository billingRepository, - IIdGenerator idGenerator) - : IRequestHandler -{ - /// - public async Task Handle(GenerateSubscriptionBillingCommand request, CancellationToken cancellationToken) - { - // 1. 查询订阅详情(含租户/套餐信息) - var detail = await subscriptionRepository.GetDetailAsync(request.SubscriptionId, cancellationToken); - if (detail is null) - { - throw new BusinessException(ErrorCodes.NotFound, "订阅不存在"); - } - - // 2. 校验套餐价格信息 - var subscription = detail.Subscription; - var package = detail.Package; - if (package is null) - { - throw new BusinessException(ErrorCodes.BusinessError, "订阅未关联有效套餐,无法生成账单"); - } - - // 3. 按订阅周期选择价格(简化规则:优先按年/按月) - var billingPeriodDays = (subscription.EffectiveTo - subscription.EffectiveFrom).TotalDays; - var amountDue = billingPeriodDays >= 300 - ? package.YearlyPrice - : package.MonthlyPrice; - - if (!amountDue.HasValue) - { - throw new BusinessException(ErrorCodes.BusinessError, "套餐价格未配置,无法生成账单"); - } - - // 4. 幂等校验:同一周期开始时间仅允许存在一张未取消账单 - var exists = await billingRepository.ExistsNotCancelledByPeriodStartAsync(subscription.TenantId, subscription.EffectiveFrom, cancellationToken); - if (exists) - { - throw new BusinessException(ErrorCodes.Conflict, "该订阅周期的账单已存在"); - } - - // 5. 构建账单实体 - var now = DateTime.UtcNow; - var statementNo = $"BIL-{now:yyyyMMdd}-{idGenerator.NextId()}"; - var lineItems = new List - { - new() - { - ItemType = "Subscription", - Description = $"套餐 {package.Name} 订阅费用", - Quantity = 1, - UnitPrice = amountDue.Value, - Amount = amountDue.Value, - DiscountRate = null - } - }; - - var billing = new TenantBillingStatement - { - TenantId = subscription.TenantId, - StatementNo = statementNo, - BillingType = BillingType.Subscription, - SubscriptionId = subscription.Id, - PeriodStart = subscription.EffectiveFrom, - PeriodEnd = subscription.EffectiveTo, - AmountDue = amountDue.Value, - DiscountAmount = 0m, - TaxAmount = 0m, - AmountPaid = 0m, - Currency = "CNY", - Status = TenantBillingStatus.Pending, - DueDate = now.AddDays(7), - LineItemsJson = JsonSerializer.Serialize(lineItems), - Notes = subscription.Notes - }; - - // 6. 持久化账单 - await billingRepository.AddAsync(billing, cancellationToken); - await billingRepository.SaveChangesAsync(cancellationToken); - - // 7. 返回详情 DTO - return billing.ToBillingDetailDto([], detail.TenantName); - } -} - diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetBillDetailQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetBillDetailQueryHandler.cs deleted file mode 100644 index c368fac..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetBillDetailQueryHandler.cs +++ /dev/null @@ -1,41 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Billings.Dto; -using TakeoutSaaS.Application.App.Billings.Queries; -using TakeoutSaaS.Domain.Tenants.Repositories; - -namespace TakeoutSaaS.Application.App.Billings.Handlers; - -/// -/// 获取账单详情查询处理器。 -/// -public sealed class GetBillDetailQueryHandler( - ITenantBillingRepository billingRepository, - ITenantPaymentRepository paymentRepository, - ITenantRepository tenantRepository) - : IRequestHandler -{ - /// - /// 处理获取账单详情请求。 - /// - /// 查询请求。 - /// 取消标记。 - /// 账单详情或 null。 - public async Task Handle(GetBillDetailQuery request, CancellationToken cancellationToken) - { - // 1. 查询账单 - var bill = await billingRepository.FindByIdAsync(request.BillId, cancellationToken); - if (bill is null) - { - return null; - } - - // 2. 查询支付记录 - var payments = await paymentRepository.GetByBillingIdAsync(request.BillId, cancellationToken); - - // 3. 查询租户名称 - var tenant = await tenantRepository.FindByIdAsync(bill.TenantId, cancellationToken); - - // 4. 返回详情 DTO - return bill.ToDetailDto(payments.ToList(), tenant?.Name); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetBillListQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetBillListQueryHandler.cs deleted file mode 100644 index 51782d5..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetBillListQueryHandler.cs +++ /dev/null @@ -1,55 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Billings.Dto; -using TakeoutSaaS.Application.App.Billings.Queries; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.App.Billings.Handlers; - -/// -/// 获取账单列表查询处理器。 -/// -public sealed class GetBillListQueryHandler( - ITenantBillingRepository billingRepository, - ITenantRepository tenantRepository) - : IRequestHandler> -{ - /// - /// 处理获取账单列表请求。 - /// - /// 查询请求。 - /// 取消标记。 - /// 分页账单列表。 - public async Task> Handle(GetBillListQuery request, CancellationToken cancellationToken) - { - // 1. 分页查询账单 - var (bills, total) = await billingRepository.SearchPagedAsync( - request.TenantId, - request.Status, - request.StartDate, - request.EndDate, - null, - null, - request.Keyword, - request.PageNumber, - request.PageSize, - cancellationToken); - - // 2. 无数据直接返回 - if (bills.Count == 0) - { - return new PagedResult([], request.PageNumber, request.PageSize, total); - } - - // 3. 批量查询租户信息 - var tenantIds = bills.Select(b => b.TenantId).Distinct().ToArray(); - var tenants = await tenantRepository.FindByIdsAsync(tenantIds, cancellationToken); - var tenantDict = tenants.ToDictionary(t => t.Id, t => t.Name); - - // 4. 映射 DTO - var result = bills.Select(b => b.ToDto(tenantDict.GetValueOrDefault(b.TenantId))).ToList(); - - // 5. 返回分页结果 - return new PagedResult(result, request.PageNumber, request.PageSize, total); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetBillingDetailQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetBillingDetailQueryHandler.cs deleted file mode 100644 index cb9ae96..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetBillingDetailQueryHandler.cs +++ /dev/null @@ -1,236 +0,0 @@ -using MediatR; -using System.Data; -using System.Data.Common; -using System.Text.Json; -using TakeoutSaaS.Application.App.Billings.Dto; -using TakeoutSaaS.Application.App.Billings.Queries; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Data; -using TakeoutSaaS.Shared.Abstractions.Exceptions; - -namespace TakeoutSaaS.Application.App.Billings.Handlers; - -/// -/// 查询账单详情处理器。 -/// -public sealed class GetBillingDetailQueryHandler( - IDapperExecutor dapperExecutor) - : IRequestHandler -{ - /// - /// 处理查询账单详情请求。 - /// - /// 查询命令。 - /// 取消标记。 - /// 账单详情 DTO。 - public async Task Handle(GetBillingDetailQuery request, CancellationToken cancellationToken) - { - // 1. 查询账单 + 支付记录(同一连接,避免多次往返) - return await dapperExecutor.QueryAsync( - DatabaseConstants.AppDataSource, - DatabaseConnectionRole.Read, - async (connection, token) => - { - // 1.1 查询账单 - await using var billCommand = CreateCommand( - connection, - BuildBillingSql(), - [ - ("billingId", request.BillingId) - ]); - - await using var billReader = await billCommand.ExecuteReaderAsync(token); - if (!await billReader.ReadAsync(token)) - { - throw new BusinessException(ErrorCodes.NotFound, "账单不存在"); - } - - // 1.2 读取账单行数据到内存(释放 Reader,避免同连接并发执行命令) - var billingId = billReader.GetInt64(0); - var tenantId = billReader.GetInt64(1); - var tenantName = billReader.IsDBNull(2) ? string.Empty : billReader.GetString(2); - long? subscriptionId = billReader.IsDBNull(3) ? null : billReader.GetInt64(3); - var statementNo = billReader.GetString(4); - var billingType = (BillingType)billReader.GetInt32(5); - var status = (TenantBillingStatus)billReader.GetInt32(6); - var periodStart = billReader.GetDateTime(7); - var periodEnd = billReader.GetDateTime(8); - var amountDue = billReader.GetDecimal(9); - var discountAmount = billReader.GetDecimal(10); - var taxAmount = billReader.GetDecimal(11); - var amountPaid = billReader.GetDecimal(12); - var currency = billReader.IsDBNull(13) ? "CNY" : billReader.GetString(13); - var dueDate = billReader.GetDateTime(14); - DateTime? reminderSentAt = billReader.IsDBNull(15) ? null : billReader.GetDateTime(15); - DateTime? overdueNotifiedAt = billReader.IsDBNull(16) ? null : billReader.GetDateTime(16); - var notes = billReader.IsDBNull(17) ? null : billReader.GetString(17); - var lineItemsJson = billReader.IsDBNull(18) ? null : billReader.GetString(18); - var createdAt = billReader.GetDateTime(19); - long? createdBy = billReader.IsDBNull(20) ? null : billReader.GetInt64(20); - DateTime? updatedAt = billReader.IsDBNull(21) ? null : billReader.GetDateTime(21); - long? updatedBy = billReader.IsDBNull(22) ? null : billReader.GetInt64(22); - - // 1.3 主动释放账单 Reader,确保后续查询不会触发 Npgsql 并发命令异常 - await billReader.DisposeAsync(); - - // 1.4 反序列化账单明细 - var lineItems = new List(); - if (!string.IsNullOrWhiteSpace(lineItemsJson)) - { - try - { - lineItems = JsonSerializer.Deserialize>(lineItemsJson) ?? []; - } - catch - { - lineItems = []; - } - } - - // 1.5 查询支付记录 - var payments = new List(); - await using var paymentCommand = CreateCommand( - connection, - BuildPaymentsSql(), - [ - ("billingId", request.BillingId) - ]); - - await using var paymentReader = await paymentCommand.ExecuteReaderAsync(token); - while (await paymentReader.ReadAsync(token)) - { - payments.Add(new PaymentRecordDto - { - Id = paymentReader.GetInt64(0), - TenantId = paymentReader.GetInt64(1), - BillingId = paymentReader.GetInt64(2), - Amount = paymentReader.GetDecimal(3), - Method = (TenantPaymentMethod)paymentReader.GetInt32(4), - Status = (TenantPaymentStatus)paymentReader.GetInt32(5), - TransactionNo = paymentReader.IsDBNull(6) ? null : paymentReader.GetString(6), - ProofUrl = paymentReader.IsDBNull(7) ? null : paymentReader.GetString(7), - Notes = paymentReader.IsDBNull(8) ? null : paymentReader.GetString(8), - VerifiedBy = paymentReader.IsDBNull(9) ? null : paymentReader.GetInt64(9), - VerifiedAt = paymentReader.IsDBNull(10) ? null : paymentReader.GetDateTime(10), - RefundReason = paymentReader.IsDBNull(11) ? null : paymentReader.GetString(11), - RefundedAt = paymentReader.IsDBNull(12) ? null : paymentReader.GetDateTime(12), - PaidAt = paymentReader.IsDBNull(13) ? null : paymentReader.GetDateTime(13), - IsVerified = !paymentReader.IsDBNull(10), - CreatedAt = paymentReader.GetDateTime(14) - }); - } - - // 1.6 组装详情 DTO - var totalAmount = amountDue - discountAmount + taxAmount; - - return new BillingDetailDto - { - Id = billingId, - TenantId = tenantId, - TenantName = tenantName, - SubscriptionId = subscriptionId, - StatementNo = statementNo, - BillingType = billingType, - Status = status, - PeriodStart = periodStart, - PeriodEnd = periodEnd, - AmountDue = amountDue, - DiscountAmount = discountAmount, - TaxAmount = taxAmount, - TotalAmount = totalAmount, - AmountPaid = amountPaid, - Currency = currency, - DueDate = dueDate, - ReminderSentAt = reminderSentAt, - OverdueNotifiedAt = overdueNotifiedAt, - LineItemsJson = lineItemsJson, - LineItems = lineItems, - Payments = payments, - Notes = notes, - CreatedAt = createdAt, - CreatedBy = createdBy, - UpdatedAt = updatedAt, - UpdatedBy = updatedBy - }; - }, - cancellationToken); - } - - private static string BuildBillingSql() - { - return """ - select - b."Id", - b."TenantId", - t."Name" as "TenantName", - b."SubscriptionId", - b."StatementNo", - b."BillingType", - b."Status", - b."PeriodStart", - b."PeriodEnd", - b."AmountDue", - b."DiscountAmount", - b."TaxAmount", - b."AmountPaid", - b."Currency", - b."DueDate", - b."ReminderSentAt", - b."OverdueNotifiedAt", - b."Notes", - b."LineItemsJson", - b."CreatedAt", - b."CreatedBy", - b."UpdatedAt", - b."UpdatedBy" - from public.tenant_billing_statements b - join public.tenants t on t."Id" = b."TenantId" and t."DeletedAt" is null - where b."DeletedAt" is null - and b."Id" = @billingId - limit 1; - """; - } - - private static string BuildPaymentsSql() - { - return """ - select - p."Id", - p."TenantId", - p."BillingStatementId", - p."Amount", - p."Method", - p."Status", - p."TransactionNo", - p."ProofUrl", - p."Notes", - p."VerifiedBy", - p."VerifiedAt", - p."RefundReason", - p."RefundedAt", - p."PaidAt", - p."CreatedAt" - from public.tenant_payments p - where p."DeletedAt" is null - and p."BillingStatementId" = @billingId - order by p."CreatedAt" desc; - """; - } - - private static DbCommand CreateCommand(IDbConnection connection, string sql, (string Name, object? Value)[] parameters) - { - var command = connection.CreateCommand(); - command.CommandText = sql; - - foreach (var (name, value) in parameters) - { - var p = command.CreateParameter(); - p.ParameterName = name; - p.Value = value ?? DBNull.Value; - command.Parameters.Add(p); - } - - return (DbCommand)command; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetBillingListQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetBillingListQueryHandler.cs deleted file mode 100644 index f88c50a..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetBillingListQueryHandler.cs +++ /dev/null @@ -1,250 +0,0 @@ -using MediatR; -using System.Data; -using System.Data.Common; -using TakeoutSaaS.Application.App.Billings.Dto; -using TakeoutSaaS.Application.App.Billings.Queries; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Data; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Results; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Billings.Handlers; - -/// -/// 分页查询账单列表处理器。 -/// -public sealed class GetBillingListQueryHandler( - IDapperExecutor dapperExecutor, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - /// - /// 处理分页查询账单列表请求。 - /// - /// 查询命令。 - /// 取消标记。 - /// 分页账单列表 DTO。 - public async Task> Handle(GetBillingListQuery request, CancellationToken cancellationToken) - { - // 1. 校验租户上下文(租户端禁止跨租户) - var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (currentTenantId <= 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识"); - } - - // 2. (空行后) 禁止跨租户查询 - if (request.TenantId.HasValue && request.TenantId.Value != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户查询账单"); - } - var tenantId = currentTenantId; - - // 3. (空行后) 参数规范化 - var page = request.PageNumber <= 0 ? 1 : request.PageNumber; - var pageSize = request.PageSize is <= 0 or > 200 ? 20 : request.PageSize; - var keyword = string.IsNullOrWhiteSpace(request.Keyword) ? null : request.Keyword.Trim(); - var minAmount = request.MinAmount; - var maxAmount = request.MaxAmount; - var offset = (page - 1) * pageSize; - - // 1.1 金额区间规范化(避免 min > max 导致结果为空) - if (minAmount.HasValue && maxAmount.HasValue && minAmount.Value > maxAmount.Value) - { - (minAmount, maxAmount) = (maxAmount, minAmount); - } - - // 2. 排序白名单(防 SQL 注入) - var orderBy = request.SortBy?.Trim() switch - { - "DueDate" => "b.\"DueDate\"", - "AmountDue" => "b.\"AmountDue\"", - "PeriodStart" => "b.\"PeriodStart\"", - "PeriodEnd" => "b.\"PeriodEnd\"", - "CreatedAt" => "b.\"CreatedAt\"", - _ => "b.\"CreatedAt\"" - }; - - // 3. 查询总数 + 列表 - return await dapperExecutor.QueryAsync( - DatabaseConstants.AppDataSource, - DatabaseConnectionRole.Read, - async (connection, token) => - { - // 3.1 统计总数 - var total = await ExecuteScalarIntAsync( - connection, - BuildCountSql(), - [ - ("tenantId", tenantId), - ("status", request.Status.HasValue ? (int)request.Status.Value : null), - ("billingType", request.BillingType.HasValue ? (int)request.BillingType.Value : null), - ("startDate", request.StartDate), - ("endDate", request.EndDate), - ("minAmount", minAmount), - ("maxAmount", maxAmount), - ("keyword", keyword) - ], - token); - - // 3.2 查询列表 - var listSql = BuildListSql(orderBy, request.SortDesc); - await using var listCommand = CreateCommand( - connection, - listSql, - [ - ("tenantId", tenantId), - ("status", request.Status.HasValue ? (int)request.Status.Value : null), - ("billingType", request.BillingType.HasValue ? (int)request.BillingType.Value : null), - ("startDate", request.StartDate), - ("endDate", request.EndDate), - ("minAmount", minAmount), - ("maxAmount", maxAmount), - ("keyword", keyword), - ("offset", offset), - ("limit", pageSize) - ]); - - await using var reader = await listCommand.ExecuteReaderAsync(token); - var now = DateTime.UtcNow; - var items = new List(); - while (await reader.ReadAsync(token)) - { - var dueDate = reader.GetDateTime(13); - var status = (TenantBillingStatus)reader.GetInt32(12); - var amountDue = reader.GetDecimal(8); - var discountAmount = reader.GetDecimal(9); - var taxAmount = reader.GetDecimal(10); - var totalAmount = amountDue - discountAmount + taxAmount; - - // 3.2.1 逾期辅助字段 - var isOverdue = status is TenantBillingStatus.Overdue - || (status is TenantBillingStatus.Pending && dueDate < now); - var overdueDays = dueDate < now ? (int)(now - dueDate).TotalDays : 0; - - items.Add(new BillingListDto - { - Id = reader.GetInt64(0), - TenantId = reader.GetInt64(1), - TenantName = reader.IsDBNull(2) ? string.Empty : reader.GetString(2), - SubscriptionId = reader.IsDBNull(3) ? null : reader.GetInt64(3), - StatementNo = reader.GetString(4), - BillingType = (BillingType)reader.GetInt32(5), - PeriodStart = reader.GetDateTime(6), - PeriodEnd = reader.GetDateTime(7), - AmountDue = amountDue, - DiscountAmount = discountAmount, - TaxAmount = taxAmount, - TotalAmount = totalAmount, - AmountPaid = reader.GetDecimal(11), - Currency = reader.IsDBNull(14) ? "CNY" : reader.GetString(14), - Status = status, - DueDate = dueDate, - IsOverdue = isOverdue, - OverdueDays = overdueDays, - CreatedAt = reader.GetDateTime(15), - UpdatedAt = reader.IsDBNull(16) ? null : reader.GetDateTime(16) - }); - } - - // 3.3 返回分页 - return new PagedResult(items, page, pageSize, total); - }, - cancellationToken); - } - - private static string BuildCountSql() - { - return """ - select count(*) - from public.tenant_billing_statements b - join public.tenants t on t."Id" = b."TenantId" and t."DeletedAt" is null - where b."DeletedAt" is null - and b."TenantId" = @tenantId - and (@status::int is null or b."Status" = @status) - and (@billingType::int is null or b."BillingType" = @billingType) - and (@startDate::timestamp with time zone is null or b."PeriodStart" >= @startDate) - and (@endDate::timestamp with time zone is null or b."PeriodEnd" <= @endDate) - and (@minAmount::numeric is null or b."AmountDue" >= @minAmount) - and (@maxAmount::numeric is null or b."AmountDue" <= @maxAmount) - and ( - @keyword::text is null - or b."StatementNo" ilike ('%' || @keyword::text || '%') - or t."Name" ilike ('%' || @keyword::text || '%') - ); - """; - } - - private static string BuildListSql(string orderBy, bool sortDesc) - { - var direction = sortDesc ? "desc" : "asc"; - - return $""" - select - b."Id", - b."TenantId", - t."Name" as "TenantName", - b."SubscriptionId", - b."StatementNo", - b."BillingType", - b."PeriodStart", - b."PeriodEnd", - b."AmountDue", - b."DiscountAmount", - b."TaxAmount", - b."AmountPaid", - b."Status", - b."DueDate", - b."Currency", - b."CreatedAt", - b."UpdatedAt" - from public.tenant_billing_statements b - join public.tenants t on t."Id" = b."TenantId" and t."DeletedAt" is null - where b."DeletedAt" is null - and b."TenantId" = @tenantId - and (@status::int is null or b."Status" = @status) - and (@billingType::int is null or b."BillingType" = @billingType) - and (@startDate::timestamp with time zone is null or b."PeriodStart" >= @startDate) - and (@endDate::timestamp with time zone is null or b."PeriodEnd" <= @endDate) - and (@minAmount::numeric is null or b."AmountDue" >= @minAmount) - and (@maxAmount::numeric is null or b."AmountDue" <= @maxAmount) - and ( - @keyword::text is null - or b."StatementNo" ilike ('%' || @keyword::text || '%') - or t."Name" ilike ('%' || @keyword::text || '%') - ) - order by {orderBy} {direction} - offset @offset - limit @limit; - """; - } - - private static async Task ExecuteScalarIntAsync( - IDbConnection connection, - string sql, - (string Name, object? Value)[] parameters, - CancellationToken cancellationToken) - { - await using var command = CreateCommand(connection, sql, parameters); - var result = await command.ExecuteScalarAsync(cancellationToken); - return result is null or DBNull ? 0 : Convert.ToInt32(result); - } - - private static DbCommand CreateCommand(IDbConnection connection, string sql, (string Name, object? Value)[] parameters) - { - var command = connection.CreateCommand(); - command.CommandText = sql; - - foreach (var (name, value) in parameters) - { - var p = command.CreateParameter(); - p.ParameterName = name; - p.Value = value ?? DBNull.Value; - command.Parameters.Add(p); - } - - return (DbCommand)command; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetBillingPaymentsQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetBillingPaymentsQueryHandler.cs deleted file mode 100644 index b7df3b5..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetBillingPaymentsQueryHandler.cs +++ /dev/null @@ -1,139 +0,0 @@ -using MediatR; -using System.Data; -using System.Data.Common; -using TakeoutSaaS.Application.App.Billings.Dto; -using TakeoutSaaS.Application.App.Billings.Queries; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Data; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Domain.Tenants.Enums; - -namespace TakeoutSaaS.Application.App.Billings.Handlers; - -/// -/// 查询账单支付记录处理器。 -/// -public sealed class GetBillingPaymentsQueryHandler( - IDapperExecutor dapperExecutor) - : IRequestHandler> -{ - /// - /// 处理查询账单支付记录请求。 - /// - /// 查询命令。 - /// 取消标记。 - /// 支付记录列表 DTO。 - public async Task> Handle(GetBillingPaymentsQuery request, CancellationToken cancellationToken) - { - // 1. 校验账单是否存在 - return await dapperExecutor.QueryAsync( - DatabaseConstants.AppDataSource, - DatabaseConnectionRole.Read, - async (connection, token) => - { - // 1.1 校验账单存在 - var exists = await ExecuteScalarIntAsync( - connection, - """ - select 1 - from public.tenant_billing_statements b - where b."DeletedAt" is null - and b."Id" = @billingId - limit 1; - """, - [ - ("billingId", request.BillingId) - ], - token); - - if (exists == 0) - { - throw new BusinessException(ErrorCodes.NotFound, "账单不存在"); - } - - // 1.2 查询支付记录 - await using var command = CreateCommand( - connection, - """ - select - p."Id", - p."TenantId", - p."BillingStatementId", - p."Amount", - p."Method", - p."Status", - p."TransactionNo", - p."ProofUrl", - p."Notes", - p."VerifiedBy", - p."VerifiedAt", - p."RefundReason", - p."RefundedAt", - p."PaidAt", - p."CreatedAt" - from public.tenant_payments p - where p."DeletedAt" is null - and p."BillingStatementId" = @billingId - order by p."CreatedAt" desc; - """, - [ - ("billingId", request.BillingId) - ]); - - await using var reader = await command.ExecuteReaderAsync(token); - var results = new List(); - while (await reader.ReadAsync(token)) - { - results.Add(new PaymentRecordDto - { - Id = reader.GetInt64(0), - TenantId = reader.GetInt64(1), - BillingId = reader.GetInt64(2), - Amount = reader.GetDecimal(3), - Method = (TenantPaymentMethod)reader.GetInt32(4), - Status = (TenantPaymentStatus)reader.GetInt32(5), - TransactionNo = reader.IsDBNull(6) ? null : reader.GetString(6), - ProofUrl = reader.IsDBNull(7) ? null : reader.GetString(7), - Notes = reader.IsDBNull(8) ? null : reader.GetString(8), - VerifiedBy = reader.IsDBNull(9) ? null : reader.GetInt64(9), - VerifiedAt = reader.IsDBNull(10) ? null : reader.GetDateTime(10), - RefundReason = reader.IsDBNull(11) ? null : reader.GetString(11), - RefundedAt = reader.IsDBNull(12) ? null : reader.GetDateTime(12), - PaidAt = reader.IsDBNull(13) ? null : reader.GetDateTime(13), - IsVerified = !reader.IsDBNull(10), - CreatedAt = reader.GetDateTime(14) - }); - } - - return results; - }, - cancellationToken); - } - - private static async Task ExecuteScalarIntAsync( - IDbConnection connection, - string sql, - (string Name, object? Value)[] parameters, - CancellationToken cancellationToken) - { - await using var command = CreateCommand(connection, sql, parameters); - var result = await command.ExecuteScalarAsync(cancellationToken); - return result is null or DBNull ? 0 : Convert.ToInt32(result); - } - - private static DbCommand CreateCommand(IDbConnection connection, string sql, (string Name, object? Value)[] parameters) - { - var command = connection.CreateCommand(); - command.CommandText = sql; - - foreach (var (name, value) in parameters) - { - var p = command.CreateParameter(); - p.ParameterName = name; - p.Value = value ?? DBNull.Value; - command.Parameters.Add(p); - } - - return (DbCommand)command; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetBillingStatisticsQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetBillingStatisticsQueryHandler.cs deleted file mode 100644 index 4410e6e..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetBillingStatisticsQueryHandler.cs +++ /dev/null @@ -1,204 +0,0 @@ -using MediatR; -using System.Data; -using System.Data.Common; -using TakeoutSaaS.Application.App.Billings.Dto; -using TakeoutSaaS.Application.App.Billings.Queries; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Data; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Billings.Handlers; - -/// -/// 查询账单统计数据处理器。 -/// -public sealed class GetBillingStatisticsQueryHandler( - IDapperExecutor dapperExecutor, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - /// 处理查询账单统计数据请求。 - /// - /// 查询命令。 - /// 取消标记。 - /// 账单统计数据 DTO。 - public async Task Handle(GetBillingStatisticsQuery request, CancellationToken cancellationToken) - { - // 1. 校验租户上下文(租户端禁止跨租户) - var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (currentTenantId <= 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识"); - } - - // 2. (空行后) 禁止跨租户统计 - if (request.TenantId.HasValue && request.TenantId.Value != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户统计账单"); - } - var tenantId = currentTenantId; - - // 3. (空行后) 参数规范化 - var startDate = request.StartDate ?? DateTime.UtcNow.AddMonths(-1); - var endDate = request.EndDate ?? DateTime.UtcNow; - var groupBy = NormalizeGroupBy(request.GroupBy); - - // 2. 查询统计数据(总览 + 趋势) - return await dapperExecutor.QueryAsync( - DatabaseConstants.AppDataSource, - DatabaseConnectionRole.Read, - async (connection, token) => - { - // 2.1 总览统计 - await using var summaryCommand = CreateCommand( - connection, - BuildSummarySql(), - [ - ("tenantId", tenantId), - ("startDate", startDate), - ("endDate", endDate), - ("now", DateTime.UtcNow) - ]); - - await using var summaryReader = await summaryCommand.ExecuteReaderAsync(token); - await summaryReader.ReadAsync(token); - - var totalCount = summaryReader.IsDBNull(0) ? 0 : summaryReader.GetInt32(0); - var pendingCount = summaryReader.IsDBNull(1) ? 0 : summaryReader.GetInt32(1); - var paidCount = summaryReader.IsDBNull(2) ? 0 : summaryReader.GetInt32(2); - var overdueCount = summaryReader.IsDBNull(3) ? 0 : summaryReader.GetInt32(3); - var cancelledCount = summaryReader.IsDBNull(4) ? 0 : summaryReader.GetInt32(4); - var totalAmountDue = summaryReader.IsDBNull(5) ? 0m : summaryReader.GetDecimal(5); - var totalAmountPaid = summaryReader.IsDBNull(6) ? 0m : summaryReader.GetDecimal(6); - var totalAmountUnpaid = summaryReader.IsDBNull(7) ? 0m : summaryReader.GetDecimal(7); - var totalOverdueAmount = summaryReader.IsDBNull(8) ? 0m : summaryReader.GetDecimal(8); - - // 2.2 趋势数据 - await using var trendCommand = CreateCommand( - connection, - BuildTrendSql(groupBy), - [ - ("tenantId", tenantId), - ("startDate", startDate), - ("endDate", endDate) - ]); - - await using var trendReader = await trendCommand.ExecuteReaderAsync(token); - var amountDueTrend = new Dictionary(); - var amountPaidTrend = new Dictionary(); - var countTrend = new Dictionary(); - while (await trendReader.ReadAsync(token)) - { - var bucket = trendReader.GetDateTime(0); - var key = bucket.ToString("yyyy-MM-dd"); - - amountDueTrend[key] = trendReader.IsDBNull(1) ? 0m : trendReader.GetDecimal(1); - amountPaidTrend[key] = trendReader.IsDBNull(2) ? 0m : trendReader.GetDecimal(2); - countTrend[key] = trendReader.IsDBNull(3) ? 0 : trendReader.GetInt32(3); - } - - // 2.3 组装 DTO - return new BillingStatisticsDto - { - TenantId = tenantId, - StartDate = startDate, - EndDate = endDate, - GroupBy = groupBy, - TotalCount = totalCount, - PendingCount = pendingCount, - PaidCount = paidCount, - OverdueCount = overdueCount, - CancelledCount = cancelledCount, - TotalAmountDue = totalAmountDue, - TotalAmountPaid = totalAmountPaid, - TotalAmountUnpaid = totalAmountUnpaid, - TotalOverdueAmount = totalOverdueAmount, - AmountDueTrend = amountDueTrend, - AmountPaidTrend = amountPaidTrend, - CountTrend = countTrend - }; - }, - cancellationToken); - } - - private static string NormalizeGroupBy(string? groupBy) - { - return groupBy?.Trim() switch - { - "Week" => "Week", - "Month" => "Month", - _ => "Day" - }; - } - - private static string BuildSummarySql() - { - return """ - select - count(*)::int as "TotalCount", - coalesce(sum(case when b."Status" = 0 then 1 else 0 end), 0)::int as "PendingCount", - coalesce(sum(case when b."Status" = 1 then 1 else 0 end), 0)::int as "PaidCount", - coalesce(sum(case when b."Status" = 2 then 1 else 0 end), 0)::int as "OverdueCount", - coalesce(sum(case when b."Status" = 3 then 1 else 0 end), 0)::int as "CancelledCount", - coalesce(sum(b."AmountDue"), 0)::numeric as "TotalAmountDue", - coalesce(sum(b."AmountPaid"), 0)::numeric as "TotalAmountPaid", - coalesce(sum((b."AmountDue" - b."DiscountAmount" + b."TaxAmount") - b."AmountPaid"), 0)::numeric as "TotalAmountUnpaid", - coalesce(sum( - case - when b."Status" in (0, 2) and b."DueDate" < @now - then (b."AmountDue" - b."DiscountAmount" + b."TaxAmount") - b."AmountPaid" - else 0 - end - ), 0)::numeric as "TotalOverdueAmount" - from public.tenant_billing_statements b - where b."DeletedAt" is null - and b."TenantId" = @tenantId - and b."PeriodStart" >= @startDate - and b."PeriodEnd" <= @endDate; - """; - } - - private static string BuildTrendSql(string groupBy) - { - var dateTrunc = groupBy switch - { - "Week" => "week", - "Month" => "month", - _ => "day" - }; - - return $""" - select - date_trunc('{dateTrunc}', b."PeriodStart") as "Bucket", - coalesce(sum(b."AmountDue"), 0)::numeric as "AmountDue", - coalesce(sum(b."AmountPaid"), 0)::numeric as "AmountPaid", - count(*)::int as "Count" - from public.tenant_billing_statements b - where b."DeletedAt" is null - and b."TenantId" = @tenantId - and b."PeriodStart" >= @startDate - and b."PeriodEnd" <= @endDate - group by 1 - order by 1 asc; - """; - } - - private static DbCommand CreateCommand(IDbConnection connection, string sql, (string Name, object? Value)[] parameters) - { - var command = connection.CreateCommand(); - command.CommandText = sql; - - foreach (var (name, value) in parameters) - { - var p = command.CreateParameter(); - p.ParameterName = name; - p.Value = value ?? DBNull.Value; - command.Parameters.Add(p); - } - - return (DbCommand)command; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetOverdueBillingsQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetOverdueBillingsQueryHandler.cs deleted file mode 100644 index b75fecd..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetOverdueBillingsQueryHandler.cs +++ /dev/null @@ -1,172 +0,0 @@ -using MediatR; -using System.Data; -using System.Data.Common; -using TakeoutSaaS.Application.App.Billings.Dto; -using TakeoutSaaS.Application.App.Billings.Queries; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Data; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.App.Billings.Handlers; - -/// -/// 查询逾期账单列表处理器。 -/// -public sealed class GetOverdueBillingsQueryHandler( - IDapperExecutor dapperExecutor) - : IRequestHandler> -{ - /// - /// 处理查询逾期账单列表请求。 - /// - /// 查询命令。 - /// 取消标记。 - /// 分页逾期账单列表 DTO。 - public async Task> Handle(GetOverdueBillingsQuery request, CancellationToken cancellationToken) - { - // 1. 参数规范化 - var page = request.PageNumber <= 0 ? 1 : request.PageNumber; - var pageSize = request.PageSize is <= 0 or > 200 ? 20 : request.PageSize; - var offset = (page - 1) * pageSize; - var now = DateTime.UtcNow; - - // 2. 查询总数 + 列表 - return await dapperExecutor.QueryAsync( - DatabaseConstants.AppDataSource, - DatabaseConnectionRole.Read, - async (connection, token) => - { - // 2.1 统计总数 - var total = await ExecuteScalarIntAsync( - connection, - BuildCountSql(), - [ - ("now", now) - ], - token); - - // 2.2 查询列表 - await using var listCommand = CreateCommand( - connection, - BuildListSql(), - [ - ("now", now), - ("offset", offset), - ("limit", pageSize) - ]); - - await using var reader = await listCommand.ExecuteReaderAsync(token); - var items = new List(); - while (await reader.ReadAsync(token)) - { - var dueDate = reader.GetDateTime(13); - var status = (TenantBillingStatus)reader.GetInt32(12); - var amountDue = reader.GetDecimal(8); - var discountAmount = reader.GetDecimal(9); - var taxAmount = reader.GetDecimal(10); - var totalAmount = amountDue - discountAmount + taxAmount; - var overdueDays = dueDate < now ? (int)(now - dueDate).TotalDays : 0; - - items.Add(new BillingListDto - { - Id = reader.GetInt64(0), - TenantId = reader.GetInt64(1), - TenantName = reader.IsDBNull(2) ? string.Empty : reader.GetString(2), - SubscriptionId = reader.IsDBNull(3) ? null : reader.GetInt64(3), - StatementNo = reader.GetString(4), - BillingType = (BillingType)reader.GetInt32(5), - PeriodStart = reader.GetDateTime(6), - PeriodEnd = reader.GetDateTime(7), - AmountDue = amountDue, - DiscountAmount = discountAmount, - TaxAmount = taxAmount, - TotalAmount = totalAmount, - AmountPaid = reader.GetDecimal(11), - Status = status, - DueDate = dueDate, - Currency = reader.IsDBNull(14) ? "CNY" : reader.GetString(14), - IsOverdue = true, - OverdueDays = overdueDays, - CreatedAt = reader.GetDateTime(15), - UpdatedAt = reader.IsDBNull(16) ? null : reader.GetDateTime(16) - }); - } - - // 2.3 返回分页 - return new PagedResult(items, page, pageSize, total); - }, - cancellationToken); - } - - private static string BuildCountSql() - { - return """ - select count(*) - from public.tenant_billing_statements b - join public.tenants t on t."Id" = b."TenantId" and t."DeletedAt" is null - where b."DeletedAt" is null - and b."DueDate" < @now - and b."Status" in (0, 2); - """; - } - - private static string BuildListSql() - { - return """ - select - b."Id", - b."TenantId", - t."Name" as "TenantName", - b."SubscriptionId", - b."StatementNo", - b."BillingType", - b."PeriodStart", - b."PeriodEnd", - b."AmountDue", - b."DiscountAmount", - b."TaxAmount", - b."AmountPaid", - b."Status", - b."DueDate", - b."Currency", - b."CreatedAt", - b."UpdatedAt" - from public.tenant_billing_statements b - join public.tenants t on t."Id" = b."TenantId" and t."DeletedAt" is null - where b."DeletedAt" is null - and b."DueDate" < @now - and b."Status" in (0, 2) - order by b."DueDate" asc - offset @offset - limit @limit; - """; - } - - private static async Task ExecuteScalarIntAsync( - IDbConnection connection, - string sql, - (string Name, object? Value)[] parameters, - CancellationToken cancellationToken) - { - await using var command = CreateCommand(connection, sql, parameters); - var result = await command.ExecuteScalarAsync(cancellationToken); - return result is null or DBNull ? 0 : Convert.ToInt32(result); - } - - private static DbCommand CreateCommand(IDbConnection connection, string sql, (string Name, object? Value)[] parameters) - { - var command = connection.CreateCommand(); - command.CommandText = sql; - - foreach (var (name, value) in parameters) - { - var p = command.CreateParameter(); - p.ParameterName = name; - p.Value = value ?? DBNull.Value; - command.Parameters.Add(p); - } - - return (DbCommand)command; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetTenantPaymentsQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetTenantPaymentsQueryHandler.cs deleted file mode 100644 index 80d1538..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetTenantPaymentsQueryHandler.cs +++ /dev/null @@ -1,28 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Billings.Dto; -using TakeoutSaaS.Application.App.Billings.Queries; -using TakeoutSaaS.Domain.Tenants.Repositories; - -namespace TakeoutSaaS.Application.App.Billings.Handlers; - -/// -/// 获取租户支付记录查询处理器。 -/// -public sealed class GetTenantPaymentsQueryHandler(ITenantPaymentRepository paymentRepository) - : IRequestHandler> -{ - /// - /// 处理获取支付记录请求。 - /// - /// 查询请求。 - /// 取消标记。 - /// 支付记录列表。 - public async Task> Handle(GetTenantPaymentsQuery request, CancellationToken cancellationToken) - { - // 1. 查询支付记录 - var payments = await paymentRepository.GetByBillingIdAsync(request.BillId, cancellationToken); - - // 2. 映射并返回 DTO - return payments.Select(p => p.ToDto()).ToList(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/ProcessOverdueBillingsCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/ProcessOverdueBillingsCommandHandler.cs deleted file mode 100644 index 0cb8c5b..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/ProcessOverdueBillingsCommandHandler.cs +++ /dev/null @@ -1,20 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Billings.Commands; -using TakeoutSaaS.Domain.Tenants.Services; - -namespace TakeoutSaaS.Application.App.Billings.Handlers; - -/// -/// 处理逾期账单命令处理器(后台任务)。 -/// -public sealed class ProcessOverdueBillingsCommandHandler( - IBillingDomainService billingDomainService) - : IRequestHandler -{ - /// - public async Task Handle(ProcessOverdueBillingsCommand request, CancellationToken cancellationToken) - { - // 1. 委托领域服务执行逾期账单处理(Pending && DueDate < Now -> Overdue) - return await billingDomainService.ProcessOverdueBillingsAsync(cancellationToken); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/RecordPaymentCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/RecordPaymentCommandHandler.cs deleted file mode 100644 index 47a81aa..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/RecordPaymentCommandHandler.cs +++ /dev/null @@ -1,81 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Billings.Commands; -using TakeoutSaaS.Application.App.Billings.Dto; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Ids; - -namespace TakeoutSaaS.Application.App.Billings.Handlers; - -/// -/// 记录支付处理器。 -/// -public sealed class RecordPaymentCommandHandler( - ITenantBillingRepository billingRepository, - ITenantPaymentRepository paymentRepository, - IIdGenerator idGenerator) - : IRequestHandler -{ - /// - /// 处理记录支付请求。 - /// - /// 记录支付命令。 - /// 取消标记。 - /// 支付 DTO。 - public async Task Handle(RecordPaymentCommand request, CancellationToken cancellationToken) - { - // 1. 查询账单 - var billing = await billingRepository.FindByIdAsync(request.BillingId, cancellationToken); - if (billing is null) - { - throw new BusinessException(ErrorCodes.NotFound, "账单不存在"); - } - - // 2. 业务规则检查 - if (billing.Status == TenantBillingStatus.Paid) - { - throw new BusinessException(ErrorCodes.BusinessError, "已支付账单不允许重复收款"); - } - - if (billing.Status == TenantBillingStatus.Cancelled) - { - throw new BusinessException(ErrorCodes.BusinessError, "已取消账单不允许收款"); - } - - // 3. 幂等校验:交易号唯一 - if (!string.IsNullOrWhiteSpace(request.TransactionNo)) - { - var exists = await paymentRepository.GetByTransactionNoAsync(request.TransactionNo.Trim(), cancellationToken); - if (exists is not null) - { - throw new BusinessException(ErrorCodes.Conflict, "交易号已存在,疑似重复提交"); - } - } - - // 4. 构建支付记录(默认待审核) - var now = DateTime.UtcNow; - var payment = new TenantPayment - { - Id = idGenerator.NextId(), - TenantId = billing.TenantId, - BillingStatementId = request.BillingId, - Amount = request.Amount, - Method = request.Method, - Status = TenantPaymentStatus.Pending, - TransactionNo = string.IsNullOrWhiteSpace(request.TransactionNo) ? null : request.TransactionNo.Trim(), - ProofUrl = request.ProofUrl, - PaidAt = now, - Notes = request.Notes - }; - - // 5. 持久化变更 - await paymentRepository.AddAsync(payment, cancellationToken); - await paymentRepository.SaveChangesAsync(cancellationToken); - - // 6. 返回 DTO - return payment.ToPaymentRecordDto(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/UpdateBillStatusCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/UpdateBillStatusCommandHandler.cs deleted file mode 100644 index 9a6f33b..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/UpdateBillStatusCommandHandler.cs +++ /dev/null @@ -1,50 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Billings.Commands; -using TakeoutSaaS.Application.App.Billings.Dto; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; - -namespace TakeoutSaaS.Application.App.Billings.Handlers; - -/// -/// 更新账单状态处理器。 -/// -public sealed class UpdateBillStatusCommandHandler( - ITenantBillingRepository billingRepository, - ITenantRepository tenantRepository) - : IRequestHandler -{ - /// - /// 处理更新账单状态请求。 - /// - /// 更新命令。 - /// 取消标记。 - /// 账单 DTO 或 null。 - public async Task Handle(UpdateBillStatusCommand request, CancellationToken cancellationToken) - { - // 1. 查询账单 - var bill = await billingRepository.FindByIdAsync(request.BillId, cancellationToken); - if (bill is null) - { - return null; - } - - // 2. 更新状态 - bill.Status = request.Status; - if (!string.IsNullOrWhiteSpace(request.Notes)) - { - bill.LineItemsJson = request.Notes; - } - - // 3. 持久化变更 - await billingRepository.UpdateAsync(bill, cancellationToken); - await billingRepository.SaveChangesAsync(cancellationToken); - - // 4. 查询租户名称 - var tenant = await tenantRepository.FindByIdAsync(bill.TenantId, cancellationToken); - - // 5. 返回 DTO - return bill.ToDto(tenant?.Name); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/UpdateBillingStatusCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/UpdateBillingStatusCommandHandler.cs deleted file mode 100644 index 049bdd1..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/UpdateBillingStatusCommandHandler.cs +++ /dev/null @@ -1,54 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Billings.Commands; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; - -namespace TakeoutSaaS.Application.App.Billings.Handlers; - -/// -/// 更新账单状态命令处理器。 -/// -public sealed class UpdateBillingStatusCommandHandler( - ITenantBillingRepository billingRepository) - : IRequestHandler -{ - /// - public async Task Handle(UpdateBillingStatusCommand request, CancellationToken cancellationToken) - { - // 1. 查询账单 - var billing = await billingRepository.FindByIdAsync(request.BillingId, cancellationToken); - if (billing is null) - { - throw new BusinessException(ErrorCodes.NotFound, "账单不存在"); - } - - // 2. 状态转换规则校验 - if (billing.Status == TenantBillingStatus.Paid && request.NewStatus != TenantBillingStatus.Paid) - { - throw new BusinessException(ErrorCodes.BusinessError, "已支付账单不允许改为其他状态"); - } - - if (billing.Status == TenantBillingStatus.Cancelled) - { - throw new BusinessException(ErrorCodes.BusinessError, "已取消账单不允许变更状态"); - } - - // 3. 更新状态与备注 - billing.Status = request.NewStatus; - if (!string.IsNullOrWhiteSpace(request.Notes)) - { - billing.Notes = string.IsNullOrWhiteSpace(billing.Notes) - ? $"[状态变更] {request.Notes}" - : $"{billing.Notes}\n[状态变更] {request.Notes}"; - } - - // 4. 持久化 - await billingRepository.UpdateAsync(billing, cancellationToken); - await billingRepository.SaveChangesAsync(cancellationToken); - - return Unit.Value; - } -} - diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/VerifyPaymentCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/VerifyPaymentCommandHandler.cs deleted file mode 100644 index 0d58db4..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/VerifyPaymentCommandHandler.cs +++ /dev/null @@ -1,73 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Billings.Commands; -using TakeoutSaaS.Application.App.Billings.Dto; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Security; - -namespace TakeoutSaaS.Application.App.Billings.Handlers; - -/// -/// 审核支付命令处理器。 -/// -public sealed class VerifyPaymentCommandHandler( - ITenantPaymentRepository paymentRepository, - ITenantBillingRepository billingRepository, - ICurrentUserAccessor currentUserAccessor) - : IRequestHandler -{ - /// - public async Task Handle(VerifyPaymentCommand request, CancellationToken cancellationToken) - { - // 1. 校验操作者身份 - if (!currentUserAccessor.IsAuthenticated || currentUserAccessor.UserId <= 0) - { - throw new BusinessException(ErrorCodes.Unauthorized, "未登录或无效的操作者身份"); - } - - // 2. 查询支付记录 - var payment = await paymentRepository.FindByIdAsync(request.PaymentId, cancellationToken); - if (payment is null) - { - throw new BusinessException(ErrorCodes.NotFound, "支付记录不存在"); - } - - // 3. 查询关联账单 - var billing = await billingRepository.FindByIdAsync(payment.BillingStatementId, cancellationToken); - if (billing is null) - { - throw new BusinessException(ErrorCodes.NotFound, "关联账单不存在"); - } - - // 4. 归一化审核备注 - var normalizedNotes = string.IsNullOrWhiteSpace(request.Notes) ? null : request.Notes.Trim(); - - // 5. 根据审核结果更新支付与账单状态 - if (request.Approved) - { - payment.Verify(currentUserAccessor.UserId); - payment.Notes = normalizedNotes; - - billing.MarkAsPaid(payment.Amount, payment.TransactionNo ?? string.Empty); - } - else - { - payment.Reject(currentUserAccessor.UserId, normalizedNotes ?? string.Empty); - payment.Notes = normalizedNotes; - } - - // 6. 持久化更新状态 - await paymentRepository.UpdateAsync(payment, cancellationToken); - if (request.Approved) - { - await billingRepository.UpdateAsync(billing, cancellationToken); - } - - // 7. 保存数据库更改 - await paymentRepository.SaveChangesAsync(cancellationToken); - - // 8. 返回 DTO - return payment.ToPaymentRecordDto(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Queries/ExportBillingsQuery.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Queries/ExportBillingsQuery.cs deleted file mode 100644 index c800a21..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Queries/ExportBillingsQuery.cs +++ /dev/null @@ -1,19 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.App.Billings.Queries; - -/// -/// 导出账单(Excel/PDF/CSV)。 -/// -public sealed record ExportBillingsQuery : IRequest -{ - /// - /// 要导出的账单 ID 列表。 - /// - public long[] BillingIds { get; init; } = []; - - /// - /// 导出格式(Excel/Pdf/Csv)。 - /// - public string Format { get; init; } = "Excel"; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetBillDetailQuery.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetBillDetailQuery.cs deleted file mode 100644 index d155acd..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetBillDetailQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Billings.Dto; - -namespace TakeoutSaaS.Application.App.Billings.Queries; - -/// -/// 获取账单详情查询。 -/// -public sealed record GetBillDetailQuery : IRequest -{ - /// - /// 账单 ID(雪花算法)。 - /// - public long BillId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetBillListQuery.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetBillListQuery.cs deleted file mode 100644 index 903c333..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetBillListQuery.cs +++ /dev/null @@ -1,47 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Billings.Dto; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.App.Billings.Queries; - -/// -/// 获取账单列表查询。 -/// -public sealed record GetBillListQuery : IRequest> -{ - /// - /// 页码(从 1 开始)。 - /// - public int PageNumber { get; init; } = 1; - - /// - /// 页大小。 - /// - public int PageSize { get; init; } = 20; - - /// - /// 租户 ID 筛选(可选)。 - /// - public long? TenantId { get; init; } - - /// - /// 状态筛选(可选)。 - /// - public TenantBillingStatus? Status { get; init; } - - /// - /// 开始日期筛选(可选)。 - /// - public DateTime? StartDate { get; init; } - - /// - /// 结束日期筛选(可选)。 - /// - public DateTime? EndDate { get; init; } - - /// - /// 搜索关键词(账单号或租户名)。 - /// - public string? Keyword { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetBillingDetailQuery.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetBillingDetailQuery.cs deleted file mode 100644 index c4fc6fd..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetBillingDetailQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Billings.Dto; - -namespace TakeoutSaaS.Application.App.Billings.Queries; - -/// -/// 查询账单详情(含明细项)。 -/// -public sealed record GetBillingDetailQuery : IRequest -{ - /// - /// 账单 ID(雪花算法)。 - /// - public long BillingId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetBillingListQuery.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetBillingListQuery.cs deleted file mode 100644 index 7d3a7f9..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetBillingListQuery.cs +++ /dev/null @@ -1,72 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Billings.Dto; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.App.Billings.Queries; - -/// -/// 分页查询账单列表。 -/// -public sealed record GetBillingListQuery : IRequest> -{ - /// - /// 租户 ID(可选,默认当前租户;禁止跨租户)。 - /// - public long? TenantId { get; init; } - - /// - /// 账单状态筛选。 - /// - public TenantBillingStatus? Status { get; init; } - - /// - /// 账单类型筛选。 - /// - public BillingType? BillingType { get; init; } - - /// - /// 账单起始时间(UTC)筛选。 - /// - public DateTime? StartDate { get; init; } - - /// - /// 账单结束时间(UTC)筛选。 - /// - public DateTime? EndDate { get; init; } - - /// - /// 关键词搜索(账单编号)。 - /// - public string? Keyword { get; init; } - - /// - /// 最小应付金额筛选(包含)。 - /// - public decimal? MinAmount { get; init; } - - /// - /// 最大应付金额筛选(包含)。 - /// - public decimal? MaxAmount { get; init; } - - /// - /// 页码(从 1 开始)。 - /// - public int PageNumber { get; init; } = 1; - - /// - /// 每页条数。 - /// - public int PageSize { get; init; } = 20; - - /// - /// 排序字段(DueDate/CreatedAt/AmountDue)。 - /// - public string? SortBy { get; init; } - - /// - /// 是否降序排序。 - /// - public bool SortDesc { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetBillingPaymentsQuery.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetBillingPaymentsQuery.cs deleted file mode 100644 index 04e01c4..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetBillingPaymentsQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Billings.Dto; - -namespace TakeoutSaaS.Application.App.Billings.Queries; - -/// -/// 查询账单的支付记录。 -/// -public sealed record GetBillingPaymentsQuery : IRequest> -{ - /// - /// 账单 ID(雪花算法)。 - /// - public long BillingId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetBillingStatisticsQuery.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetBillingStatisticsQuery.cs deleted file mode 100644 index f8e27dc..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetBillingStatisticsQuery.cs +++ /dev/null @@ -1,30 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Billings.Dto; - -namespace TakeoutSaaS.Application.App.Billings.Queries; - -/// -/// 查询账单统计数据。 -/// -public sealed record GetBillingStatisticsQuery : IRequest -{ - /// - /// 租户 ID(可选,默认当前租户;禁止跨租户)。 - /// - public long? TenantId { get; init; } - - /// - /// 统计开始时间(UTC)。 - /// - public DateTime? StartDate { get; init; } - - /// - /// 统计结束时间(UTC)。 - /// - public DateTime? EndDate { get; init; } - - /// - /// 分组方式(Day/Week/Month)。 - /// - public string? GroupBy { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetOverdueBillingsQuery.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetOverdueBillingsQuery.cs deleted file mode 100644 index 171019e..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetOverdueBillingsQuery.cs +++ /dev/null @@ -1,21 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Billings.Dto; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.App.Billings.Queries; - -/// -/// 查询逾期账单列表。 -/// -public sealed record GetOverdueBillingsQuery : IRequest> -{ - /// - /// 页码(从 1 开始)。 - /// - public int PageNumber { get; init; } = 1; - - /// - /// 每页条数。 - /// - public int PageSize { get; init; } = 20; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetTenantPaymentsQuery.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetTenantPaymentsQuery.cs deleted file mode 100644 index 986ca41..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Queries/GetTenantPaymentsQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Billings.Dto; - -namespace TakeoutSaaS.Application.App.Billings.Queries; - -/// -/// 获取租户支付记录查询。 -/// -public sealed record GetTenantPaymentsQuery : IRequest> -{ - /// - /// 账单 ID(雪花算法)。 - /// - public long BillId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Validators/ConfirmPaymentCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Validators/ConfirmPaymentCommandValidator.cs deleted file mode 100644 index d1d8f75..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Validators/ConfirmPaymentCommandValidator.cs +++ /dev/null @@ -1,50 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Billings.Commands; - -namespace TakeoutSaaS.Application.App.Billings.Validators; - -/// -/// 一键确认收款命令验证器。 -/// -public sealed class ConfirmPaymentCommandValidator : AbstractValidator -{ - public ConfirmPaymentCommandValidator() - { - // 1. 账单 ID 必填 - RuleFor(x => x.BillingId) - .GreaterThan(0) - .WithMessage("账单 ID 必须大于 0"); - - // 2. 支付金额必须大于 0 - RuleFor(x => x.Amount) - .GreaterThan(0) - .WithMessage("支付金额必须大于 0") - .LessThanOrEqualTo(1_000_000_000) - .WithMessage("支付金额不能超过 10 亿"); - - // 3. 支付方式必填 - RuleFor(x => x.Method) - .IsInEnum() - .WithMessage("支付方式无效"); - - // 4. 交易号必填 - RuleFor(x => x.TransactionNo) - .NotEmpty() - .WithMessage("交易号不能为空") - .MaximumLength(64) - .WithMessage("交易号不能超过 64 个字符"); - - // 5. 支付凭证 URL(可选) - RuleFor(x => x.ProofUrl) - .MaximumLength(500) - .WithMessage("支付凭证 URL 不能超过 500 个字符") - .When(x => !string.IsNullOrWhiteSpace(x.ProofUrl)); - - // 6. 备注(可选) - RuleFor(x => x.Notes) - .MaximumLength(500) - .WithMessage("备注不能超过 500 个字符") - .When(x => !string.IsNullOrWhiteSpace(x.Notes)); - } -} - diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Validators/CreateBillingCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Validators/CreateBillingCommandValidator.cs deleted file mode 100644 index 14483f7..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Validators/CreateBillingCommandValidator.cs +++ /dev/null @@ -1,73 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Billings.Commands; - -namespace TakeoutSaaS.Application.App.Billings.Validators; - -/// -/// 创建账单命令验证器。 -/// -public sealed class CreateBillingCommandValidator : AbstractValidator -{ - public CreateBillingCommandValidator() - { - // 1. 租户 ID 必填 - RuleFor(x => x.TenantId) - .GreaterThan(0) - .WithMessage("租户 ID 必须大于 0"); - - // 2. 账单类型必填 - RuleFor(x => x.BillingType) - .IsInEnum() - .WithMessage("账单类型无效"); - - // 3. 应付金额必须大于 0 - RuleFor(x => x.AmountDue) - .GreaterThan(0) - .WithMessage("应付金额必须大于 0"); - - // 4. 到期日必须是未来时间 - RuleFor(x => x.DueDate) - .GreaterThan(DateTime.UtcNow) - .WithMessage("到期日必须是未来时间"); - - // 5. 账单明细至少包含一项 - RuleFor(x => x.LineItems) - .NotEmpty() - .WithMessage("账单明细不能为空"); - - // 6. 账单明细项验证 - RuleForEach(x => x.LineItems) - .ChildRules(lineItem => - { - lineItem.RuleFor(x => x.ItemType) - .NotEmpty() - .WithMessage("账单明细类型不能为空") - .MaximumLength(50) - .WithMessage("账单明细类型不能超过 50 个字符"); - - lineItem.RuleFor(x => x.Description) - .NotEmpty() - .WithMessage("账单明细描述不能为空") - .MaximumLength(200) - .WithMessage("账单明细描述不能超过 200 个字符"); - - lineItem.RuleFor(x => x.Quantity) - .GreaterThan(0) - .WithMessage("账单明细数量必须大于 0"); - - lineItem.RuleFor(x => x.UnitPrice) - .GreaterThanOrEqualTo(0) - .WithMessage("账单明细单价不能为负数"); - - lineItem.RuleFor(x => x.Amount) - .GreaterThanOrEqualTo(0) - .WithMessage("账单明细金额不能为负数"); - }); - - // 7. 备注长度限制(可选) - RuleFor(x => x.Notes) - .MaximumLength(500) - .WithMessage("备注不能超过 500 个字符") - .When(x => !string.IsNullOrWhiteSpace(x.Notes)); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Validators/RecordPaymentCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Validators/RecordPaymentCommandValidator.cs deleted file mode 100644 index 266eb1e..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Validators/RecordPaymentCommandValidator.cs +++ /dev/null @@ -1,49 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Billings.Commands; - -namespace TakeoutSaaS.Application.App.Billings.Validators; - -/// -/// 记录支付命令验证器。 -/// -public sealed class RecordPaymentCommandValidator : AbstractValidator -{ - public RecordPaymentCommandValidator() - { - // 1. 账单 ID 必填 - RuleFor(x => x.BillingId) - .GreaterThan(0) - .WithMessage("账单 ID 必须大于 0"); - - // 2. 支付金额必须大于 0 - RuleFor(x => x.Amount) - .GreaterThan(0) - .WithMessage("支付金额必须大于 0") - .LessThanOrEqualTo(1_000_000_000) - .WithMessage("支付金额不能超过 10 亿"); - - // 3. 支付方式必填 - RuleFor(x => x.Method) - .IsInEnum() - .WithMessage("支付方式无效"); - - // 4. 交易号必填 - RuleFor(x => x.TransactionNo) - .NotEmpty() - .WithMessage("交易号不能为空") - .MaximumLength(64) - .WithMessage("交易号不能超过 64 个字符"); - - // 5. 支付凭证 URL(可选) - RuleFor(x => x.ProofUrl) - .MaximumLength(500) - .WithMessage("支付凭证 URL 不能超过 500 个字符") - .When(x => !string.IsNullOrWhiteSpace(x.ProofUrl)); - - // 6. 备注(可选) - RuleFor(x => x.Notes) - .MaximumLength(500) - .WithMessage("备注不能超过 500 个字符") - .When(x => !string.IsNullOrWhiteSpace(x.Notes)); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Validators/UpdateBillingStatusCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Validators/UpdateBillingStatusCommandValidator.cs deleted file mode 100644 index 025b6ed..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Validators/UpdateBillingStatusCommandValidator.cs +++ /dev/null @@ -1,30 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Billings.Commands; - -namespace TakeoutSaaS.Application.App.Billings.Validators; - -/// -/// 更新账单状态命令验证器。 -/// -public sealed class UpdateBillingStatusCommandValidator : AbstractValidator -{ - public UpdateBillingStatusCommandValidator() - { - // 1. 账单 ID 必填 - RuleFor(x => x.BillingId) - .GreaterThan(0) - .WithMessage("账单 ID 必须大于 0"); - - // 2. 状态枚举校验 - RuleFor(x => x.NewStatus) - .IsInEnum() - .WithMessage("新状态无效"); - - // 3. 备注长度限制(可选) - RuleFor(x => x.Notes) - .MaximumLength(500) - .WithMessage("备注不能超过 500 个字符") - .When(x => !string.IsNullOrWhiteSpace(x.Notes)); - } -} - diff --git a/src/Application/TakeoutSaaS.Application/App/Deliveries/Commands/CreateDeliveryOrderCommand.cs b/src/Application/TakeoutSaaS.Application/App/Deliveries/Commands/CreateDeliveryOrderCommand.cs deleted file mode 100644 index 8f5a2b7..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Deliveries/Commands/CreateDeliveryOrderCommand.cs +++ /dev/null @@ -1,66 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Deliveries.Dto; -using TakeoutSaaS.Domain.Deliveries.Enums; - -namespace TakeoutSaaS.Application.App.Deliveries.Commands; - -/// -/// 创建配送单命令。 -/// -public sealed class CreateDeliveryOrderCommand : IRequest -{ - /// - /// 订单 ID。 - /// - public long OrderId { get; set; } - - /// - /// 服务商。 - /// - public DeliveryProvider Provider { get; set; } = DeliveryProvider.InHouse; - - /// - /// 第三方单号。 - /// - public string? ProviderOrderId { get; set; } - - /// - /// 状态。 - /// - public DeliveryStatus Status { get; set; } = DeliveryStatus.Pending; - - /// - /// 配送费。 - /// - public decimal? DeliveryFee { get; set; } - - /// - /// 骑手姓名。 - /// - public string? CourierName { get; set; } - - /// - /// 骑手电话。 - /// - public string? CourierPhone { get; set; } - - /// - /// 下发时间。 - /// - public DateTime? DispatchedAt { get; set; } - - /// - /// 取餐时间。 - /// - public DateTime? PickedUpAt { get; set; } - - /// - /// 完成时间。 - /// - public DateTime? DeliveredAt { get; set; } - - /// - /// 异常原因。 - /// - public string? FailureReason { get; set; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Deliveries/Commands/DeleteDeliveryOrderCommand.cs b/src/Application/TakeoutSaaS.Application/App/Deliveries/Commands/DeleteDeliveryOrderCommand.cs deleted file mode 100644 index b05162d..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Deliveries/Commands/DeleteDeliveryOrderCommand.cs +++ /dev/null @@ -1,14 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.App.Deliveries.Commands; - -/// -/// 删除配送单命令。 -/// -public sealed class DeleteDeliveryOrderCommand : IRequest -{ - /// - /// 配送单 ID。 - /// - public long DeliveryOrderId { get; set; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Deliveries/Commands/UpdateDeliveryOrderCommand.cs b/src/Application/TakeoutSaaS.Application/App/Deliveries/Commands/UpdateDeliveryOrderCommand.cs deleted file mode 100644 index cb94be2..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Deliveries/Commands/UpdateDeliveryOrderCommand.cs +++ /dev/null @@ -1,71 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Deliveries.Dto; -using TakeoutSaaS.Domain.Deliveries.Enums; - -namespace TakeoutSaaS.Application.App.Deliveries.Commands; - -/// -/// 更新配送单命令。 -/// -public sealed record UpdateDeliveryOrderCommand : IRequest -{ - /// - /// 配送单 ID。 - /// - public long DeliveryOrderId { get; init; } - - /// - /// 订单 ID。 - /// - public long OrderId { get; init; } - - /// - /// 服务商。 - /// - public DeliveryProvider Provider { get; init; } = DeliveryProvider.InHouse; - - /// - /// 第三方单号。 - /// - public string? ProviderOrderId { get; init; } - - /// - /// 状态。 - /// - public DeliveryStatus Status { get; init; } = DeliveryStatus.Pending; - - /// - /// 配送费。 - /// - public decimal? DeliveryFee { get; init; } - - /// - /// 骑手姓名。 - /// - public string? CourierName { get; init; } - - /// - /// 骑手电话。 - /// - public string? CourierPhone { get; init; } - - /// - /// 下发时间。 - /// - public DateTime? DispatchedAt { get; init; } - - /// - /// 取餐时间。 - /// - public DateTime? PickedUpAt { get; init; } - - /// - /// 完成时间。 - /// - public DateTime? DeliveredAt { get; init; } - - /// - /// 异常原因。 - /// - public string? FailureReason { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Deliveries/Dto/DeliveryEventDto.cs b/src/Application/TakeoutSaaS.Application/App/Deliveries/Dto/DeliveryEventDto.cs deleted file mode 100644 index a8d2a7e..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Deliveries/Dto/DeliveryEventDto.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Deliveries.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Deliveries.Dto; - -/// -/// 配送事件 DTO。 -/// -public sealed class DeliveryEventDto -{ - /// - /// 事件 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 配送单 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long DeliveryOrderId { get; init; } - - /// - /// 事件类型。 - /// - public DeliveryEventType EventType { get; init; } - - /// - /// 描述。 - /// - public string? Message { get; init; } - - /// - /// 事件时间。 - /// - public DateTime OccurredAt { get; init; } - - /// - /// 原始载荷。 - /// - public string? Payload { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Deliveries/Dto/DeliveryOrderDto.cs b/src/Application/TakeoutSaaS.Application/App/Deliveries/Dto/DeliveryOrderDto.cs deleted file mode 100644 index 641d67a..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Deliveries/Dto/DeliveryOrderDto.cs +++ /dev/null @@ -1,89 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Deliveries.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Deliveries.Dto; - -/// -/// 配送单 DTO。 -/// -public sealed class DeliveryOrderDto -{ - /// - /// 配送单 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 租户 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 订单 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long OrderId { get; init; } - - /// - /// 配送服务商。 - /// - public DeliveryProvider Provider { get; init; } - - /// - /// 第三方配送单号。 - /// - public string? ProviderOrderId { get; init; } - - /// - /// 状态。 - /// - public DeliveryStatus Status { get; init; } - - /// - /// 配送费。 - /// - public decimal? DeliveryFee { get; init; } - - /// - /// 骑手姓名。 - /// - public string? CourierName { get; init; } - - /// - /// 骑手电话。 - /// - public string? CourierPhone { get; init; } - - /// - /// 下发时间。 - /// - public DateTime? DispatchedAt { get; init; } - - /// - /// 取餐时间。 - /// - public DateTime? PickedUpAt { get; init; } - - /// - /// 完成时间。 - /// - public DateTime? DeliveredAt { get; init; } - - /// - /// 异常原因。 - /// - public string? FailureReason { get; init; } - - /// - /// 事件列表。 - /// - public IReadOnlyList Events { get; init; } = Array.Empty(); - - /// - /// 创建时间。 - /// - public DateTime CreatedAt { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Deliveries/Handlers/CreateDeliveryOrderCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Deliveries/Handlers/CreateDeliveryOrderCommandHandler.cs deleted file mode 100644 index ad4149f..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Deliveries/Handlers/CreateDeliveryOrderCommandHandler.cs +++ /dev/null @@ -1,72 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Deliveries.Commands; -using TakeoutSaaS.Application.App.Deliveries.Dto; -using TakeoutSaaS.Domain.Deliveries.Entities; -using TakeoutSaaS.Domain.Deliveries.Repositories; - -namespace TakeoutSaaS.Application.App.Deliveries.Handlers; - -/// -/// 创建配送单命令处理器。 -/// -public sealed class CreateDeliveryOrderCommandHandler(IDeliveryRepository deliveryRepository, ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(CreateDeliveryOrderCommand request, CancellationToken cancellationToken) - { - // 1. 构建配送单实体 - var deliveryOrder = new DeliveryOrder - { - OrderId = request.OrderId, - Provider = request.Provider, - ProviderOrderId = request.ProviderOrderId?.Trim(), - Status = request.Status, - DeliveryFee = request.DeliveryFee, - CourierName = request.CourierName?.Trim(), - CourierPhone = request.CourierPhone?.Trim(), - DispatchedAt = request.DispatchedAt, - PickedUpAt = request.PickedUpAt, - DeliveredAt = request.DeliveredAt, - FailureReason = request.FailureReason?.Trim() - }; - - // 2. 持久化配送单 - await deliveryRepository.AddDeliveryOrderAsync(deliveryOrder, cancellationToken); - await deliveryRepository.SaveChangesAsync(cancellationToken); - - // 3. 记录日志 - logger.LogInformation("创建配送单 {DeliveryOrderId} 对应订单 {OrderId}", deliveryOrder.Id, deliveryOrder.OrderId); - - // 4. 映射 DTO 返回 - return MapToDto(deliveryOrder, []); - } - - private static DeliveryOrderDto MapToDto(DeliveryOrder deliveryOrder, IReadOnlyList events) => new() - { - Id = deliveryOrder.Id, - TenantId = deliveryOrder.TenantId, - OrderId = deliveryOrder.OrderId, - Provider = deliveryOrder.Provider, - ProviderOrderId = deliveryOrder.ProviderOrderId, - Status = deliveryOrder.Status, - DeliveryFee = deliveryOrder.DeliveryFee, - CourierName = deliveryOrder.CourierName, - CourierPhone = deliveryOrder.CourierPhone, - DispatchedAt = deliveryOrder.DispatchedAt, - PickedUpAt = deliveryOrder.PickedUpAt, - DeliveredAt = deliveryOrder.DeliveredAt, - FailureReason = deliveryOrder.FailureReason, - CreatedAt = deliveryOrder.CreatedAt, - Events = events.Select(x => new DeliveryEventDto - { - Id = x.Id, - DeliveryOrderId = x.DeliveryOrderId, - EventType = x.EventType, - Message = x.Message, - OccurredAt = x.OccurredAt, - Payload = x.Payload - }).ToList() - }; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Deliveries/Handlers/DeleteDeliveryOrderCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Deliveries/Handlers/DeleteDeliveryOrderCommandHandler.cs deleted file mode 100644 index 308c942..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Deliveries/Handlers/DeleteDeliveryOrderCommandHandler.cs +++ /dev/null @@ -1,38 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Deliveries.Commands; -using TakeoutSaaS.Domain.Deliveries.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Deliveries.Handlers; - -/// -/// 删除配送单命令处理器。 -/// -public sealed class DeleteDeliveryOrderCommandHandler( - IDeliveryRepository deliveryRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(DeleteDeliveryOrderCommand request, CancellationToken cancellationToken) - { - // 1. 获取租户并定位配送单 - var tenantId = tenantProvider.GetCurrentTenantId(); - var existing = await deliveryRepository.FindByIdAsync(request.DeliveryOrderId, tenantId, cancellationToken); - if (existing == null) - { - return false; - } - - // 2. 删除并保存 - await deliveryRepository.DeleteDeliveryOrderAsync(request.DeliveryOrderId, tenantId, cancellationToken); - await deliveryRepository.SaveChangesAsync(cancellationToken); - - // 3. 记录删除日志 - logger.LogInformation("删除配送单 {DeliveryOrderId}", request.DeliveryOrderId); - - return true; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Deliveries/Handlers/GetDeliveryOrderByIdQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Deliveries/Handlers/GetDeliveryOrderByIdQueryHandler.cs deleted file mode 100644 index d863d4b..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Deliveries/Handlers/GetDeliveryOrderByIdQueryHandler.cs +++ /dev/null @@ -1,64 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Deliveries.Dto; -using TakeoutSaaS.Application.App.Deliveries.Queries; -using TakeoutSaaS.Domain.Deliveries.Entities; -using TakeoutSaaS.Domain.Deliveries.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Deliveries.Handlers; - -/// -/// 配送单详情查询处理器。 -/// -public sealed class GetDeliveryOrderByIdQueryHandler( - IDeliveryRepository deliveryRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - public async Task Handle(GetDeliveryOrderByIdQuery request, CancellationToken cancellationToken) - { - // 1. 读取当前租户标识 - var tenantId = tenantProvider.GetCurrentTenantId(); - - // 2. 查询配送单主体 - var order = await deliveryRepository.FindByIdAsync(request.DeliveryOrderId, tenantId, cancellationToken); - if (order == null) - { - return null; - } - - // 3. 查询配送事件明细 - var events = await deliveryRepository.GetEventsAsync(order.Id, tenantId, cancellationToken); - - // 4. 映射为 DTO 返回 - return MapToDto(order, events); - } - - private static DeliveryOrderDto MapToDto(DeliveryOrder deliveryOrder, IReadOnlyList events) => new() - { - Id = deliveryOrder.Id, - TenantId = deliveryOrder.TenantId, - OrderId = deliveryOrder.OrderId, - Provider = deliveryOrder.Provider, - ProviderOrderId = deliveryOrder.ProviderOrderId, - Status = deliveryOrder.Status, - DeliveryFee = deliveryOrder.DeliveryFee, - CourierName = deliveryOrder.CourierName, - CourierPhone = deliveryOrder.CourierPhone, - DispatchedAt = deliveryOrder.DispatchedAt, - PickedUpAt = deliveryOrder.PickedUpAt, - DeliveredAt = deliveryOrder.DeliveredAt, - FailureReason = deliveryOrder.FailureReason, - CreatedAt = deliveryOrder.CreatedAt, - Events = events.Select(x => new DeliveryEventDto - { - Id = x.Id, - DeliveryOrderId = x.DeliveryOrderId, - EventType = x.EventType, - Message = x.Message, - OccurredAt = x.OccurredAt, - Payload = x.Payload - }).ToList() - }; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Deliveries/Handlers/SearchDeliveryOrdersQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Deliveries/Handlers/SearchDeliveryOrdersQueryHandler.cs deleted file mode 100644 index 7fcdd5a..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Deliveries/Handlers/SearchDeliveryOrdersQueryHandler.cs +++ /dev/null @@ -1,71 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Deliveries.Dto; -using TakeoutSaaS.Application.App.Deliveries.Queries; -using TakeoutSaaS.Domain.Deliveries.Repositories; -using TakeoutSaaS.Shared.Abstractions.Results; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Deliveries.Handlers; - -/// -/// 配送单列表查询处理器。 -/// -public sealed class SearchDeliveryOrdersQueryHandler( - IDeliveryRepository deliveryRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - /// - public async Task> Handle(SearchDeliveryOrdersQuery request, CancellationToken cancellationToken) - { - // 1. 获取当前租户标识 - var tenantId = tenantProvider.GetCurrentTenantId(); - - // 2. 查询配送单列表(租户隔离) - var orders = await deliveryRepository.SearchAsync(tenantId, request.Status, request.OrderId, cancellationToken); - - // 3. 本地排序 - var sorted = ApplySorting(orders, request.SortBy, request.SortDescending); - - // 4. 本地分页 - var paged = sorted - .Skip((request.Page - 1) * request.PageSize) - .Take(request.PageSize) - .ToList(); - - // 5. 映射 DTO - var items = paged.Select(order => new DeliveryOrderDto - { - Id = order.Id, - TenantId = order.TenantId, - OrderId = order.OrderId, - Provider = order.Provider, - ProviderOrderId = order.ProviderOrderId, - Status = order.Status, - DeliveryFee = order.DeliveryFee, - CourierName = order.CourierName, - CourierPhone = order.CourierPhone, - DispatchedAt = order.DispatchedAt, - PickedUpAt = order.PickedUpAt, - DeliveredAt = order.DeliveredAt, - FailureReason = order.FailureReason, - CreatedAt = order.CreatedAt - }).ToList(); - - // 6. 返回分页结果 - return new PagedResult(items, request.Page, request.PageSize, orders.Count); - } - - private static IOrderedEnumerable ApplySorting( - IReadOnlyCollection orders, - string? sortBy, - bool sortDescending) - { - return sortBy?.ToLowerInvariant() switch - { - "status" => sortDescending ? orders.OrderByDescending(x => x.Status) : orders.OrderBy(x => x.Status), - "provider" => sortDescending ? orders.OrderByDescending(x => x.Provider) : orders.OrderBy(x => x.Provider), - _ => sortDescending ? orders.OrderByDescending(x => x.CreatedAt) : orders.OrderBy(x => x.CreatedAt) - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Deliveries/Handlers/UpdateDeliveryOrderCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Deliveries/Handlers/UpdateDeliveryOrderCommandHandler.cs deleted file mode 100644 index 0c3f2c2..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Deliveries/Handlers/UpdateDeliveryOrderCommandHandler.cs +++ /dev/null @@ -1,84 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Deliveries.Commands; -using TakeoutSaaS.Application.App.Deliveries.Dto; -using TakeoutSaaS.Domain.Deliveries.Entities; -using TakeoutSaaS.Domain.Deliveries.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Deliveries.Handlers; - -/// -/// 更新配送单命令处理器。 -/// -public sealed class UpdateDeliveryOrderCommandHandler( - IDeliveryRepository deliveryRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(UpdateDeliveryOrderCommand request, CancellationToken cancellationToken) - { - // 1. 获取当前租户标识 - var tenantId = tenantProvider.GetCurrentTenantId(); - - // 2. 查询目标配送单 - var existing = await deliveryRepository.FindByIdAsync(request.DeliveryOrderId, tenantId, cancellationToken); - if (existing == null) - { - return null; - } - - // 3. 更新字段 - existing.OrderId = request.OrderId; - existing.Provider = request.Provider; - existing.ProviderOrderId = request.ProviderOrderId?.Trim(); - existing.Status = request.Status; - existing.DeliveryFee = request.DeliveryFee; - existing.CourierName = request.CourierName?.Trim(); - existing.CourierPhone = request.CourierPhone?.Trim(); - existing.DispatchedAt = request.DispatchedAt; - existing.PickedUpAt = request.PickedUpAt; - existing.DeliveredAt = request.DeliveredAt; - existing.FailureReason = request.FailureReason?.Trim(); - - // 4. 持久化变更 - await deliveryRepository.UpdateDeliveryOrderAsync(existing, cancellationToken); - await deliveryRepository.SaveChangesAsync(cancellationToken); - - // 5. 记录更新日志 - logger.LogInformation("更新配送单 {DeliveryOrderId}", existing.Id); - - // 6. 查询事件并返回映射结果 - var events = await deliveryRepository.GetEventsAsync(existing.Id, tenantId, cancellationToken); - return MapToDto(existing, events); - } - - private static DeliveryOrderDto MapToDto(DeliveryOrder deliveryOrder, IReadOnlyList events) => new() - { - Id = deliveryOrder.Id, - TenantId = deliveryOrder.TenantId, - OrderId = deliveryOrder.OrderId, - Provider = deliveryOrder.Provider, - ProviderOrderId = deliveryOrder.ProviderOrderId, - Status = deliveryOrder.Status, - DeliveryFee = deliveryOrder.DeliveryFee, - CourierName = deliveryOrder.CourierName, - CourierPhone = deliveryOrder.CourierPhone, - DispatchedAt = deliveryOrder.DispatchedAt, - PickedUpAt = deliveryOrder.PickedUpAt, - DeliveredAt = deliveryOrder.DeliveredAt, - FailureReason = deliveryOrder.FailureReason, - CreatedAt = deliveryOrder.CreatedAt, - Events = events.Select(x => new DeliveryEventDto - { - Id = x.Id, - DeliveryOrderId = x.DeliveryOrderId, - EventType = x.EventType, - Message = x.Message, - OccurredAt = x.OccurredAt, - Payload = x.Payload - }).ToList() - }; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Deliveries/Queries/GetDeliveryOrderByIdQuery.cs b/src/Application/TakeoutSaaS.Application/App/Deliveries/Queries/GetDeliveryOrderByIdQuery.cs deleted file mode 100644 index 0b89cae..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Deliveries/Queries/GetDeliveryOrderByIdQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Deliveries.Dto; - -namespace TakeoutSaaS.Application.App.Deliveries.Queries; - -/// -/// 配送单详情查询。 -/// -public sealed class GetDeliveryOrderByIdQuery : IRequest -{ - /// - /// 配送单 ID。 - /// - public long DeliveryOrderId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Deliveries/Queries/SearchDeliveryOrdersQuery.cs b/src/Application/TakeoutSaaS.Application/App/Deliveries/Queries/SearchDeliveryOrdersQuery.cs deleted file mode 100644 index 751d90c..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Deliveries/Queries/SearchDeliveryOrdersQuery.cs +++ /dev/null @@ -1,42 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Deliveries.Dto; -using TakeoutSaaS.Domain.Deliveries.Enums; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.App.Deliveries.Queries; - -/// -/// 配送单列表查询。 -/// -public sealed class SearchDeliveryOrdersQuery : IRequest> -{ - /// - /// 订单 ID(可选)。 - /// - public long? OrderId { get; init; } - - /// - /// 配送状态。 - /// - public DeliveryStatus? Status { get; init; } - - /// - /// 页码。 - /// - public int Page { get; init; } = 1; - - /// - /// 每页条数。 - /// - public int PageSize { get; init; } = 20; - - /// - /// 排序字段(createdAt/status/provider)。 - /// - public string? SortBy { get; init; } - - /// - /// 是否倒序。 - /// - public bool SortDescending { get; init; } = true; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Deliveries/Validators/CreateDeliveryOrderCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Deliveries/Validators/CreateDeliveryOrderCommandValidator.cs deleted file mode 100644 index 765e47f..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Deliveries/Validators/CreateDeliveryOrderCommandValidator.cs +++ /dev/null @@ -1,23 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Deliveries.Commands; - -namespace TakeoutSaaS.Application.App.Deliveries.Validators; - -/// -/// 创建配送单命令验证器。 -/// -public sealed class CreateDeliveryOrderCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public CreateDeliveryOrderCommandValidator() - { - RuleFor(x => x.OrderId).GreaterThan(0); - RuleFor(x => x.ProviderOrderId).MaximumLength(64); - RuleFor(x => x.CourierName).MaximumLength(64); - RuleFor(x => x.CourierPhone).MaximumLength(32); - RuleFor(x => x.FailureReason).MaximumLength(256); - RuleFor(x => x.DeliveryFee).GreaterThanOrEqualTo(0).When(x => x.DeliveryFee.HasValue); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Deliveries/Validators/SearchDeliveryOrdersQueryValidator.cs b/src/Application/TakeoutSaaS.Application/App/Deliveries/Validators/SearchDeliveryOrdersQueryValidator.cs deleted file mode 100644 index 2119152..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Deliveries/Validators/SearchDeliveryOrdersQueryValidator.cs +++ /dev/null @@ -1,20 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Deliveries.Queries; - -namespace TakeoutSaaS.Application.App.Deliveries.Validators; - -/// -/// 配送单列表查询验证器。 -/// -public sealed class SearchDeliveryOrdersQueryValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public SearchDeliveryOrdersQueryValidator() - { - RuleFor(x => x.Page).GreaterThan(0); - RuleFor(x => x.PageSize).InclusiveBetween(1, 200); - RuleFor(x => x.SortBy).MaximumLength(64); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Deliveries/Validators/UpdateDeliveryOrderCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Deliveries/Validators/UpdateDeliveryOrderCommandValidator.cs deleted file mode 100644 index e2cbc19..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Deliveries/Validators/UpdateDeliveryOrderCommandValidator.cs +++ /dev/null @@ -1,24 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Deliveries.Commands; - -namespace TakeoutSaaS.Application.App.Deliveries.Validators; - -/// -/// 更新配送单命令验证器。 -/// -public sealed class UpdateDeliveryOrderCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public UpdateDeliveryOrderCommandValidator() - { - RuleFor(x => x.DeliveryOrderId).GreaterThan(0); - RuleFor(x => x.OrderId).GreaterThan(0); - RuleFor(x => x.ProviderOrderId).MaximumLength(64); - RuleFor(x => x.CourierName).MaximumLength(64); - RuleFor(x => x.CourierPhone).MaximumLength(32); - RuleFor(x => x.FailureReason).MaximumLength(256); - RuleFor(x => x.DeliveryFee).GreaterThanOrEqualTo(0).When(x => x.DeliveryFee.HasValue); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Extensions/AppApplicationServiceCollectionExtensions.cs b/src/Application/TakeoutSaaS.Application/App/Extensions/AppApplicationServiceCollectionExtensions.cs deleted file mode 100644 index b31bbf3..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Extensions/AppApplicationServiceCollectionExtensions.cs +++ /dev/null @@ -1,36 +0,0 @@ -using FluentValidation; -using MediatR; -using Microsoft.Extensions.DependencyInjection; -using System.Reflection; -using TakeoutSaaS.Application.App.Common.Behaviors; -using TakeoutSaaS.Application.App.Personal.Services; -using TakeoutSaaS.Application.App.Personal.Validators; - -namespace TakeoutSaaS.Application.App.Extensions; - -/// -/// 业务应用层服务注册。 -/// -public static class AppApplicationServiceCollectionExtensions -{ - /// - /// 注册业务应用层(MediatR 处理器等)。 - /// - /// 服务集合。 - /// 服务集合。 - public static IServiceCollection AddAppApplication(this IServiceCollection services) - { - services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly())); - services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly()); - services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>)); - - // 1. 注册个人中心基础服务 - services.AddScoped(); - services.AddSingleton(); - services.AddSingleton(); - services.AddScoped(); - services.AddScoped(); - - return services; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Inventory/Commands/AdjustInventoryCommand.cs b/src/Application/TakeoutSaaS.Application/App/Inventory/Commands/AdjustInventoryCommand.cs deleted file mode 100644 index 7ee93f7..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Inventory/Commands/AdjustInventoryCommand.cs +++ /dev/null @@ -1,46 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Inventory.Dto; -using TakeoutSaaS.Domain.Inventory.Enums; - -namespace TakeoutSaaS.Application.App.Inventory.Commands; - -/// -/// 库存调整命令。 -/// -public sealed record AdjustInventoryCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// SKU ID。 - /// - public long ProductSkuId { get; init; } - - /// - /// 调整数量,正数入库,负数出库。 - /// - public int QuantityDelta { get; init; } - - /// - /// 调整类型。 - /// - public InventoryAdjustmentType AdjustmentType { get; init; } = InventoryAdjustmentType.Manual; - - /// - /// 原因说明。 - /// - public string? Reason { get; init; } - - /// - /// 安全库存阈值(可选)。 - /// - public int? SafetyStock { get; init; } - - /// - /// 是否售罄标记。 - /// - public bool? IsSoldOut { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Inventory/Commands/DeductInventoryCommand.cs b/src/Application/TakeoutSaaS.Application/App/Inventory/Commands/DeductInventoryCommand.cs deleted file mode 100644 index d97026f..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Inventory/Commands/DeductInventoryCommand.cs +++ /dev/null @@ -1,35 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Inventory.Dto; - -namespace TakeoutSaaS.Application.App.Inventory.Commands; - -/// -/// 扣减库存命令(履约/支付成功)。 -/// -public sealed record DeductInventoryCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// SKU ID。 - /// - public long ProductSkuId { get; init; } - - /// - /// 扣减数量。 - /// - public int Quantity { get; init; } - - /// - /// 是否预售锁定转扣减。 - /// - public bool IsPresaleOrder { get; init; } - - /// - /// 幂等键(与锁定请求一致可避免重复扣减)。 - /// - public string? IdempotencyKey { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Inventory/Commands/LockInventoryCommand.cs b/src/Application/TakeoutSaaS.Application/App/Inventory/Commands/LockInventoryCommand.cs deleted file mode 100644 index f19754b..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Inventory/Commands/LockInventoryCommand.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using MediatR; -using TakeoutSaaS.Application.App.Inventory.Dto; - -namespace TakeoutSaaS.Application.App.Inventory.Commands; - -/// -/// 锁定库存命令。 -/// -public sealed record LockInventoryCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// SKU ID。 - /// - public long ProductSkuId { get; init; } - - /// - /// 锁定数量。 - /// - public int Quantity { get; init; } - - /// - /// 是否按预售逻辑锁定。 - /// - public bool IsPresaleOrder { get; init; } - - /// - /// 锁定过期时间(UTC),超时可释放。 - /// - public DateTime? ExpiresAt { get; init; } - - /// - /// 幂等键(同一键重复调用返回同一结果)。 - /// - public string IdempotencyKey { get; init; } = string.Empty; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Inventory/Commands/ReleaseExpiredInventoryLocksCommand.cs b/src/Application/TakeoutSaaS.Application/App/Inventory/Commands/ReleaseExpiredInventoryLocksCommand.cs deleted file mode 100644 index a721448..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Inventory/Commands/ReleaseExpiredInventoryLocksCommand.cs +++ /dev/null @@ -1,8 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.App.Inventory.Commands; - -/// -/// 释放过期库存锁定命令。 -/// -public sealed record ReleaseExpiredInventoryLocksCommand : IRequest; diff --git a/src/Application/TakeoutSaaS.Application/App/Inventory/Commands/ReleaseInventoryCommand.cs b/src/Application/TakeoutSaaS.Application/App/Inventory/Commands/ReleaseInventoryCommand.cs deleted file mode 100644 index dd7c889..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Inventory/Commands/ReleaseInventoryCommand.cs +++ /dev/null @@ -1,35 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Inventory.Dto; - -namespace TakeoutSaaS.Application.App.Inventory.Commands; - -/// -/// 释放库存命令。 -/// -public sealed record ReleaseInventoryCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// SKU ID。 - /// - public long ProductSkuId { get; init; } - - /// - /// 释放数量。 - /// - public int Quantity { get; init; } - - /// - /// 是否预售锁定释放。 - /// - public bool IsPresaleOrder { get; init; } - - /// - /// 幂等键(与锁定请求一致可避免重复释放)。 - /// - public string? IdempotencyKey { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Inventory/Commands/UpsertInventoryBatchCommand.cs b/src/Application/TakeoutSaaS.Application/App/Inventory/Commands/UpsertInventoryBatchCommand.cs deleted file mode 100644 index 8943014..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Inventory/Commands/UpsertInventoryBatchCommand.cs +++ /dev/null @@ -1,45 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Inventory.Dto; - -namespace TakeoutSaaS.Application.App.Inventory.Commands; - -/// -/// 新增或更新库存批次命令。 -/// -public sealed record UpsertInventoryBatchCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// SKU ID。 - /// - public long ProductSkuId { get; init; } - - /// - /// 批次号。 - /// - public string BatchNumber { get; init; } = string.Empty; - - /// - /// 生产日期。 - /// - public DateTime? ProductionDate { get; init; } - - /// - /// 过期日期。 - /// - public DateTime? ExpireDate { get; init; } - - /// - /// 入库数量。 - /// - public int Quantity { get; init; } - - /// - /// 剩余数量。 - /// - public int RemainingQuantity { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Inventory/Dto/InventoryBatchDto.cs b/src/Application/TakeoutSaaS.Application/App/Inventory/Dto/InventoryBatchDto.cs deleted file mode 100644 index eed3c53..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Inventory/Dto/InventoryBatchDto.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Inventory.Dto; - -/// -/// 库存批次 DTO。 -/// -public sealed record InventoryBatchDto -{ - /// - /// 批次 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 门店 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long StoreId { get; init; } - - /// - /// SKU ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long ProductSkuId { get; init; } - - /// - /// 批次号。 - /// - public string BatchNumber { get; init; } = string.Empty; - - /// - /// 生产日期。 - /// - public DateTime? ProductionDate { get; init; } - - /// - /// 过期日期。 - /// - public DateTime? ExpireDate { get; init; } - - /// - /// 入库数量。 - /// - public int Quantity { get; init; } - - /// - /// 剩余数量。 - /// - public int RemainingQuantity { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Inventory/Dto/InventoryItemDto.cs b/src/Application/TakeoutSaaS.Application/App/Inventory/Dto/InventoryItemDto.cs deleted file mode 100644 index f02902a..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Inventory/Dto/InventoryItemDto.cs +++ /dev/null @@ -1,99 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Inventory.Dto; - -/// -/// 库存项 DTO。 -/// -public sealed record InventoryItemDto -{ - /// - /// 库存记录 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 租户 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 门店 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long StoreId { get; init; } - - /// - /// SKU ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long ProductSkuId { get; init; } - - /// - /// 批次号。 - /// - public string? BatchNumber { get; init; } - - /// - /// 可用库存。 - /// - public int QuantityOnHand { get; init; } - - /// - /// 已锁定库存。 - /// - public int QuantityReserved { get; init; } - - /// - /// 安全库存。 - /// - public int? SafetyStock { get; init; } - - /// - /// 储位。 - /// - public string? Location { get; init; } - - /// - /// 过期日期。 - /// - public DateTime? ExpireDate { get; init; } - - /// - /// 是否预售。 - /// - public bool IsPresale { get; init; } - - /// - /// 预售开始时间。 - /// - public DateTime? PresaleStartTime { get; init; } - - /// - /// 预售结束时间。 - /// - public DateTime? PresaleEndTime { get; init; } - - /// - /// 预售上限。 - /// - public int? PresaleCapacity { get; init; } - - /// - /// 已锁定预售量。 - /// - public int PresaleLocked { get; init; } - - /// - /// 限购数量。 - /// - public int? MaxQuantityPerOrder { get; init; } - - /// - /// 是否售罄。 - /// - public bool IsSoldOut { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/AdjustInventoryCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/AdjustInventoryCommandHandler.cs deleted file mode 100644 index 0590589..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/AdjustInventoryCommandHandler.cs +++ /dev/null @@ -1,85 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Inventory.Commands; -using TakeoutSaaS.Application.App.Inventory.Dto; -using TakeoutSaaS.Domain.Inventory.Entities; -using TakeoutSaaS.Domain.Inventory.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Inventory.Handlers; - -/// -/// 库存调整处理器。 -/// -public sealed class AdjustInventoryCommandHandler( - IInventoryRepository inventoryRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(AdjustInventoryCommand request, CancellationToken cancellationToken) - { - // 1. 读取库存 - var tenantId = tenantProvider.GetCurrentTenantId(); - var item = await inventoryRepository.GetForUpdateAsync(tenantId, request.StoreId, request.ProductSkuId, cancellationToken); - // 2. 初始化或校验存在性 - if (item is null) - { - if (request.QuantityDelta < 0) - { - throw new BusinessException(ErrorCodes.NotFound, "库存不存在,无法扣减"); - } - - // 初始化库存记录 - item = new InventoryItem - { - TenantId = tenantId, - StoreId = request.StoreId, - ProductSkuId = request.ProductSkuId, - QuantityOnHand = request.QuantityDelta, - QuantityReserved = 0, - SafetyStock = request.SafetyStock, - IsSoldOut = false - }; - await inventoryRepository.AddItemAsync(item, cancellationToken); - } - - // 3. 应用调整 - var newQuantity = item.QuantityOnHand + request.QuantityDelta; - if (newQuantity < 0) - { - throw new BusinessException(ErrorCodes.Conflict, "库存不足,无法扣减"); - } - - item.QuantityOnHand = newQuantity; - item.SafetyStock = request.SafetyStock ?? item.SafetyStock; - item.IsSoldOut = request.IsSoldOut ?? IsSoldOut(item); - - // 4. 写入调整记录 - var adjustment = new InventoryAdjustment - { - TenantId = tenantId, - InventoryItemId = item.Id, - AdjustmentType = request.AdjustmentType, - Quantity = request.QuantityDelta, - Reason = request.Reason, - OperatorId = null, - OccurredAt = DateTime.UtcNow - }; - await inventoryRepository.AddAdjustmentAsync(adjustment, cancellationToken); - await inventoryRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("调整库存 SKU {ProductSkuId} 门店 {StoreId} 变更 {Delta}", request.ProductSkuId, request.StoreId, request.QuantityDelta); - return InventoryMapping.ToDto(item); - } - - // 辅助:售罄判定 - private static bool IsSoldOut(InventoryItem item) - { - var available = item.QuantityOnHand - item.QuantityReserved - item.PresaleLocked; - var safety = item.SafetyStock ?? 0; - return available <= safety || item.QuantityOnHand <= 0; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/DeductInventoryCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/DeductInventoryCommandHandler.cs deleted file mode 100644 index 0cbde90..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/DeductInventoryCommandHandler.cs +++ /dev/null @@ -1,110 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Inventory.Commands; -using TakeoutSaaS.Application.App.Inventory.Dto; -using TakeoutSaaS.Domain.Inventory.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Inventory.Handlers; - -/// -/// 库存扣减处理器。 -/// -public sealed class DeductInventoryCommandHandler( - IInventoryRepository inventoryRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(DeductInventoryCommand request, CancellationToken cancellationToken) - { - // 1. 读取库存 - var tenantId = tenantProvider.GetCurrentTenantId(); - var item = await inventoryRepository.GetForUpdateAsync(tenantId, request.StoreId, request.ProductSkuId, cancellationToken); - if (item is null) - { - throw new BusinessException(ErrorCodes.NotFound, "库存不存在"); - } - - // 1.1 幂等:若锁记录已扣减/释放则直接返回 - if (!string.IsNullOrWhiteSpace(request.IdempotencyKey)) - { - var lockRecord = await inventoryRepository.FindLockByKeyAsync(tenantId, request.IdempotencyKey, cancellationToken); - if (lockRecord is not null) - { - if (lockRecord.Status == Domain.Inventory.Enums.InventoryLockStatus.Deducted) - { - return InventoryMapping.ToDto(item); - } - - if (lockRecord.Status == Domain.Inventory.Enums.InventoryLockStatus.Locked) - { - request = request with { Quantity = lockRecord.Quantity, IsPresaleOrder = lockRecord.IsPresale }; - await inventoryRepository.MarkLockStatusAsync(lockRecord, Domain.Inventory.Enums.InventoryLockStatus.Deducted, cancellationToken); - } - } - } - - // 2. 计算扣减来源 - var isPresale = request.IsPresaleOrder || item.IsPresale; - if (isPresale) - { - if (item.PresaleLocked < request.Quantity) - { - throw new BusinessException(ErrorCodes.Conflict, "预售锁定不足,无法扣减"); - } - - item.PresaleLocked -= request.Quantity; - } - else - { - if (item.QuantityReserved < request.Quantity) - { - throw new BusinessException(ErrorCodes.Conflict, "锁定库存不足,无法扣减"); - } - - item.QuantityReserved -= request.Quantity; - } - - var remaining = item.QuantityOnHand - request.Quantity; - if (remaining < 0) - { - throw new BusinessException(ErrorCodes.Conflict, "可用库存不足,无法扣减"); - } - - // 3. 扣减可用量并按批次消耗 - item.QuantityOnHand = remaining; - // 3.1 批次扣减(非预售) - if (!isPresale) - { - var batches = await inventoryRepository.GetBatchesForConsumeAsync(tenantId, request.StoreId, request.ProductSkuId, item.BatchConsumeStrategy, cancellationToken); - var need = request.Quantity; - foreach (var batch in batches) - { - if (need <= 0) - { - break; - } - - var take = Math.Min(batch.RemainingQuantity, need); - batch.RemainingQuantity -= take; - need -= take; - await inventoryRepository.UpdateBatchAsync(batch, cancellationToken); - } - - if (need > 0) - { - throw new BusinessException(ErrorCodes.Conflict, "批次数量不足,无法扣减"); - } - } - - item.IsSoldOut = item.QuantityOnHand - item.QuantityReserved - item.PresaleLocked <= (item.SafetyStock ?? 0); - await inventoryRepository.UpdateItemAsync(item, cancellationToken); - await inventoryRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("扣减库存 门店 {StoreId} SKU {ProductSkuId} 数量 {Quantity}", request.StoreId, request.ProductSkuId, request.Quantity); - return InventoryMapping.ToDto(item); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/GetInventoryBatchesQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/GetInventoryBatchesQueryHandler.cs deleted file mode 100644 index 3796fda..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/GetInventoryBatchesQueryHandler.cs +++ /dev/null @@ -1,26 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Inventory.Dto; -using TakeoutSaaS.Application.App.Inventory.Queries; -using TakeoutSaaS.Domain.Inventory.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Inventory.Handlers; - -/// -/// 库存批次查询处理器。 -/// -public sealed class GetInventoryBatchesQueryHandler( - IInventoryRepository inventoryRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - /// - public async Task> Handle(GetInventoryBatchesQuery request, CancellationToken cancellationToken) - { - // 1. 读取批次 - var tenantId = tenantProvider.GetCurrentTenantId(); - var batches = await inventoryRepository.GetBatchesAsync(tenantId, request.StoreId, request.ProductSkuId, cancellationToken); - // 2. 映射 - return batches.Select(InventoryMapping.ToDto).ToList(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/GetInventoryItemQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/GetInventoryItemQueryHandler.cs deleted file mode 100644 index f9a940c..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/GetInventoryItemQueryHandler.cs +++ /dev/null @@ -1,26 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Inventory.Dto; -using TakeoutSaaS.Application.App.Inventory.Queries; -using TakeoutSaaS.Domain.Inventory.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Inventory.Handlers; - -/// -/// 查询库存处理器。 -/// -public sealed class GetInventoryItemQueryHandler( - IInventoryRepository inventoryRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - public async Task Handle(GetInventoryItemQuery request, CancellationToken cancellationToken) - { - // 1. 读取库存 - var tenantId = tenantProvider.GetCurrentTenantId(); - var item = await inventoryRepository.FindBySkuAsync(tenantId, request.StoreId, request.ProductSkuId, cancellationToken); - // 2. 返回 DTO - return item is null ? null : InventoryMapping.ToDto(item); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/LockInventoryCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/LockInventoryCommandHandler.cs deleted file mode 100644 index 42f69fa..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/LockInventoryCommandHandler.cs +++ /dev/null @@ -1,92 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Inventory.Commands; -using TakeoutSaaS.Application.App.Inventory.Dto; -using TakeoutSaaS.Domain.Inventory.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Inventory.Handlers; - -/// -/// 库存锁定处理器。 -/// -public sealed class LockInventoryCommandHandler( - IInventoryRepository inventoryRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(LockInventoryCommand request, CancellationToken cancellationToken) - { - // 1. 读取库存 - var tenantId = tenantProvider.GetCurrentTenantId(); - var item = await inventoryRepository.GetForUpdateAsync(tenantId, request.StoreId, request.ProductSkuId, cancellationToken); - if (item is null) - { - throw new BusinessException(ErrorCodes.NotFound, "库存不存在"); - } - - // 1.1 幂等处理 - var existingLock = await inventoryRepository.FindLockByKeyAsync(tenantId, request.IdempotencyKey, cancellationToken); - if (existingLock is not null) - { - return InventoryMapping.ToDto(item); - } - - // 2. 校验可用量 - var now = DateTime.UtcNow; - var isPresale = request.IsPresaleOrder || item.IsPresale; - if (isPresale) - { - if (item.PresaleStartTime.HasValue && now < item.PresaleStartTime.Value) - { - throw new BusinessException(ErrorCodes.Conflict, "预售尚未开始"); - } - - if (item.PresaleEndTime.HasValue && now > item.PresaleEndTime.Value) - { - throw new BusinessException(ErrorCodes.Conflict, "预售已结束"); - } - } - - var available = isPresale - ? (item.PresaleCapacity ?? item.QuantityOnHand) - item.PresaleLocked - : item.QuantityOnHand - item.QuantityReserved; - if (available < request.Quantity) - { - throw new BusinessException(ErrorCodes.Conflict, "库存不足,无法锁定"); - } - - // 3. 执行锁定 - if (isPresale) - { - item.PresaleLocked += request.Quantity; - } - else - { - item.QuantityReserved += request.Quantity; - } - - item.IsSoldOut = item.QuantityOnHand - item.QuantityReserved - item.PresaleLocked <= (item.SafetyStock ?? 0); - await inventoryRepository.UpdateItemAsync(item, cancellationToken); - var lockRecord = new Domain.Inventory.Entities.InventoryLockRecord - { - TenantId = tenantId, - StoreId = request.StoreId, - ProductSkuId = request.ProductSkuId, - Quantity = request.Quantity, - IsPresale = isPresale, - IdempotencyKey = request.IdempotencyKey, - ExpiresAt = request.ExpiresAt, - Status = Domain.Inventory.Enums.InventoryLockStatus.Locked - }; - - await inventoryRepository.AddLockAsync(lockRecord, cancellationToken); - await inventoryRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("锁定库存 门店 {StoreId} SKU {ProductSkuId} 数量 {Quantity}", request.StoreId, request.ProductSkuId, request.Quantity); - return InventoryMapping.ToDto(item); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/ReleaseExpiredInventoryLocksCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/ReleaseExpiredInventoryLocksCommandHandler.cs deleted file mode 100644 index 0ef2884..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/ReleaseExpiredInventoryLocksCommandHandler.cs +++ /dev/null @@ -1,60 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Inventory.Commands; -using TakeoutSaaS.Domain.Inventory.Enums; -using TakeoutSaaS.Domain.Inventory.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Inventory.Handlers; - -/// -/// 释放过期锁定处理器。 -/// -public sealed class ReleaseExpiredInventoryLocksCommandHandler( - IInventoryRepository inventoryRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(ReleaseExpiredInventoryLocksCommand request, CancellationToken cancellationToken) - { - // 1. 查询过期锁 - var tenantId = tenantProvider.GetCurrentTenantId(); - var now = DateTime.UtcNow; - var expiredLocks = await inventoryRepository.FindExpiredLocksAsync(tenantId, now, cancellationToken); - if (expiredLocks.Count == 0) - { - return 0; - } - - // 2. 释放锁对应库存 - var affected = 0; - foreach (var lockRecord in expiredLocks) - { - var item = await inventoryRepository.GetForUpdateAsync(tenantId, lockRecord.StoreId, lockRecord.ProductSkuId, cancellationToken); - if (item is null) - { - continue; - } - - if (lockRecord.IsPresale) - { - item.PresaleLocked = Math.Max(0, item.PresaleLocked - lockRecord.Quantity); - } - else - { - item.QuantityReserved = Math.Max(0, item.QuantityReserved - lockRecord.Quantity); - } - - item.IsSoldOut = item.QuantityOnHand - item.QuantityReserved - item.PresaleLocked <= (item.SafetyStock ?? 0); - await inventoryRepository.UpdateItemAsync(item, cancellationToken); - await inventoryRepository.MarkLockStatusAsync(lockRecord, InventoryLockStatus.Released, cancellationToken); - affected++; - } - - await inventoryRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("释放过期库存锁定 {Count} 条", affected); - return affected; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/ReleaseInventoryCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/ReleaseInventoryCommandHandler.cs deleted file mode 100644 index b159471..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/ReleaseInventoryCommandHandler.cs +++ /dev/null @@ -1,76 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Inventory.Commands; -using TakeoutSaaS.Application.App.Inventory.Dto; -using TakeoutSaaS.Domain.Inventory.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Inventory.Handlers; - -/// -/// 库存释放处理器。 -/// -public sealed class ReleaseInventoryCommandHandler( - IInventoryRepository inventoryRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(ReleaseInventoryCommand request, CancellationToken cancellationToken) - { - // 1. 读取库存 - var tenantId = tenantProvider.GetCurrentTenantId(); - var item = await inventoryRepository.GetForUpdateAsync(tenantId, request.StoreId, request.ProductSkuId, cancellationToken); - if (item is null) - { - throw new BusinessException(ErrorCodes.NotFound, "库存不存在"); - } - - // 1.1 幂等处理:若提供键且锁记录不存在,直接视为已释放 - if (!string.IsNullOrWhiteSpace(request.IdempotencyKey)) - { - var lockRecord = await inventoryRepository.FindLockByKeyAsync(tenantId, request.IdempotencyKey, cancellationToken); - if (lockRecord is not null) - { - if (lockRecord.Status != Domain.Inventory.Enums.InventoryLockStatus.Locked) - { - return InventoryMapping.ToDto(item); - } - - // 将数量同步为锁记录数,避免重复释放不一致 - request = request with { Quantity = lockRecord.Quantity }; - await inventoryRepository.MarkLockStatusAsync(lockRecord, Domain.Inventory.Enums.InventoryLockStatus.Released, cancellationToken); - } - } - - // 2. 计算释放 - var isPresale = request.IsPresaleOrder || item.IsPresale; - if (isPresale) - { - if (item.PresaleLocked < request.Quantity) - { - throw new BusinessException(ErrorCodes.Conflict, "预售锁定不足"); - } - - item.PresaleLocked -= request.Quantity; - } - else - { - if (item.QuantityReserved < request.Quantity) - { - throw new BusinessException(ErrorCodes.Conflict, "锁定库存不足"); - } - - item.QuantityReserved -= request.Quantity; - } - - item.IsSoldOut = item.QuantityOnHand - item.QuantityReserved - item.PresaleLocked <= (item.SafetyStock ?? 0); - await inventoryRepository.UpdateItemAsync(item, cancellationToken); - await inventoryRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("释放库存 门店 {StoreId} SKU {ProductSkuId} 数量 {Quantity}", request.StoreId, request.ProductSkuId, request.Quantity); - return InventoryMapping.ToDto(item); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/UpsertInventoryBatchCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/UpsertInventoryBatchCommandHandler.cs deleted file mode 100644 index dea621d..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Inventory/Handlers/UpsertInventoryBatchCommandHandler.cs +++ /dev/null @@ -1,57 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Inventory.Commands; -using TakeoutSaaS.Application.App.Inventory.Dto; -using TakeoutSaaS.Domain.Inventory.Entities; -using TakeoutSaaS.Domain.Inventory.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Inventory.Handlers; - -/// -/// 批次维护处理器。 -/// -public sealed class UpsertInventoryBatchCommandHandler( - IInventoryRepository inventoryRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(UpsertInventoryBatchCommand request, CancellationToken cancellationToken) - { - // 1. 读取批次 - var tenantId = tenantProvider.GetCurrentTenantId(); - var batch = await inventoryRepository.GetBatchForUpdateAsync(tenantId, request.StoreId, request.ProductSkuId, request.BatchNumber, cancellationToken); - // 2. 创建或更新 - if (batch is null) - { - batch = new InventoryBatch - { - TenantId = tenantId, - StoreId = request.StoreId, - ProductSkuId = request.ProductSkuId, - BatchNumber = request.BatchNumber, - ProductionDate = request.ProductionDate, - ExpireDate = request.ExpireDate, - Quantity = request.Quantity, - RemainingQuantity = request.RemainingQuantity - }; - await inventoryRepository.AddBatchAsync(batch, cancellationToken); - } - else - { - batch.ProductionDate = request.ProductionDate; - batch.ExpireDate = request.ExpireDate; - batch.Quantity = request.Quantity; - batch.RemainingQuantity = request.RemainingQuantity; - await inventoryRepository.UpdateBatchAsync(batch, cancellationToken); - } - - await inventoryRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("维护批次 门店 {StoreId} SKU {ProductSkuId} 批次 {BatchNumber}", request.StoreId, request.ProductSkuId, request.BatchNumber); - return InventoryMapping.ToDto(batch); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Inventory/InventoryMapping.cs b/src/Application/TakeoutSaaS.Application/App/Inventory/InventoryMapping.cs deleted file mode 100644 index b4c9cbd..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Inventory/InventoryMapping.cs +++ /dev/null @@ -1,49 +0,0 @@ -using TakeoutSaaS.Application.App.Inventory.Dto; -using TakeoutSaaS.Domain.Inventory.Entities; - -namespace TakeoutSaaS.Application.App.Inventory; - -/// -/// 库存映射辅助。 -/// -public static class InventoryMapping -{ - /// - /// 映射库存 DTO。 - /// - public static InventoryItemDto ToDto(InventoryItem item) => new() - { - Id = item.Id, - TenantId = item.TenantId, - StoreId = item.StoreId, - ProductSkuId = item.ProductSkuId, - BatchNumber = item.BatchNumber, - QuantityOnHand = item.QuantityOnHand, - QuantityReserved = item.QuantityReserved, - SafetyStock = item.SafetyStock, - Location = item.Location, - ExpireDate = item.ExpireDate, - IsPresale = item.IsPresale, - PresaleStartTime = item.PresaleStartTime, - PresaleEndTime = item.PresaleEndTime, - PresaleCapacity = item.PresaleCapacity, - PresaleLocked = item.PresaleLocked, - MaxQuantityPerOrder = item.MaxQuantityPerOrder, - IsSoldOut = item.IsSoldOut - }; - - /// - /// 映射批次 DTO。 - /// - public static InventoryBatchDto ToDto(InventoryBatch batch) => new() - { - Id = batch.Id, - StoreId = batch.StoreId, - ProductSkuId = batch.ProductSkuId, - BatchNumber = batch.BatchNumber, - ProductionDate = batch.ProductionDate, - ExpireDate = batch.ExpireDate, - Quantity = batch.Quantity, - RemainingQuantity = batch.RemainingQuantity - }; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Inventory/Queries/GetInventoryBatchesQuery.cs b/src/Application/TakeoutSaaS.Application/App/Inventory/Queries/GetInventoryBatchesQuery.cs deleted file mode 100644 index c95f4cc..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Inventory/Queries/GetInventoryBatchesQuery.cs +++ /dev/null @@ -1,20 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Inventory.Dto; - -namespace TakeoutSaaS.Application.App.Inventory.Queries; - -/// -/// 查询库存批次列表。 -/// -public sealed record GetInventoryBatchesQuery : IRequest> -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// SKU ID。 - /// - public long ProductSkuId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Inventory/Queries/GetInventoryItemQuery.cs b/src/Application/TakeoutSaaS.Application/App/Inventory/Queries/GetInventoryItemQuery.cs deleted file mode 100644 index 446b59a..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Inventory/Queries/GetInventoryItemQuery.cs +++ /dev/null @@ -1,20 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Inventory.Dto; - -namespace TakeoutSaaS.Application.App.Inventory.Queries; - -/// -/// 按门店与 SKU 查询库存。 -/// -public sealed record GetInventoryItemQuery : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// SKU ID。 - /// - public long ProductSkuId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Inventory/Validators/AdjustInventoryCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Inventory/Validators/AdjustInventoryCommandValidator.cs deleted file mode 100644 index e74ea14..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Inventory/Validators/AdjustInventoryCommandValidator.cs +++ /dev/null @@ -1,21 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Inventory.Commands; - -namespace TakeoutSaaS.Application.App.Inventory.Validators; - -/// -/// 库存调整命令验证器。 -/// -public sealed class AdjustInventoryCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public AdjustInventoryCommandValidator() - { - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.ProductSkuId).GreaterThan(0); - RuleFor(x => x.QuantityDelta).NotEqual(0); - RuleFor(x => x.SafetyStock).GreaterThanOrEqualTo(0).When(x => x.SafetyStock.HasValue); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Inventory/Validators/DeductInventoryCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Inventory/Validators/DeductInventoryCommandValidator.cs deleted file mode 100644 index 53eba84..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Inventory/Validators/DeductInventoryCommandValidator.cs +++ /dev/null @@ -1,21 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Inventory.Commands; - -namespace TakeoutSaaS.Application.App.Inventory.Validators; - -/// -/// 扣减库存命令验证器。 -/// -public sealed class DeductInventoryCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public DeductInventoryCommandValidator() - { - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.ProductSkuId).GreaterThan(0); - RuleFor(x => x.Quantity).GreaterThan(0); - RuleFor(x => x.IdempotencyKey).MaximumLength(128); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Inventory/Validators/LockInventoryCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Inventory/Validators/LockInventoryCommandValidator.cs deleted file mode 100644 index 38aa7ec..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Inventory/Validators/LockInventoryCommandValidator.cs +++ /dev/null @@ -1,21 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Inventory.Commands; - -namespace TakeoutSaaS.Application.App.Inventory.Validators; - -/// -/// 库存锁定命令验证器。 -/// -public sealed class LockInventoryCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public LockInventoryCommandValidator() - { - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.ProductSkuId).GreaterThan(0); - RuleFor(x => x.Quantity).GreaterThan(0); - RuleFor(x => x.IdempotencyKey).NotEmpty().MaximumLength(128); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Inventory/Validators/ReleaseInventoryCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Inventory/Validators/ReleaseInventoryCommandValidator.cs deleted file mode 100644 index ed0b8dc..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Inventory/Validators/ReleaseInventoryCommandValidator.cs +++ /dev/null @@ -1,21 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Inventory.Commands; - -namespace TakeoutSaaS.Application.App.Inventory.Validators; - -/// -/// 释放库存命令验证器。 -/// -public sealed class ReleaseInventoryCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public ReleaseInventoryCommandValidator() - { - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.ProductSkuId).GreaterThan(0); - RuleFor(x => x.Quantity).GreaterThan(0); - RuleFor(x => x.IdempotencyKey).MaximumLength(128); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Inventory/Validators/UpsertInventoryBatchCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Inventory/Validators/UpsertInventoryBatchCommandValidator.cs deleted file mode 100644 index abcb278..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Inventory/Validators/UpsertInventoryBatchCommandValidator.cs +++ /dev/null @@ -1,22 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Inventory.Commands; - -namespace TakeoutSaaS.Application.App.Inventory.Validators; - -/// -/// 批次维护命令验证器。 -/// -public sealed class UpsertInventoryBatchCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public UpsertInventoryBatchCommandValidator() - { - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.ProductSkuId).GreaterThan(0); - RuleFor(x => x.BatchNumber).NotEmpty().MaximumLength(64); - RuleFor(x => x.Quantity).GreaterThan(0); - RuleFor(x => x.RemainingQuantity).GreaterThanOrEqualTo(0); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Commands/AddMerchantDocumentCommand.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Commands/AddMerchantDocumentCommand.cs deleted file mode 100644 index bc40f63..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Commands/AddMerchantDocumentCommand.cs +++ /dev/null @@ -1,17 +0,0 @@ -using MediatR; -using System.ComponentModel.DataAnnotations; -using TakeoutSaaS.Application.App.Merchants.Dto; -using TakeoutSaaS.Domain.Merchants.Enums; - -namespace TakeoutSaaS.Application.App.Merchants.Commands; - -/// -/// 新增商户证照。 -/// -public sealed record AddMerchantDocumentCommand( - [property: Required] long MerchantId, - [property: Required] MerchantDocumentType DocumentType, - [property: Required, MaxLength(512)] string FileUrl, - [property: MaxLength(64)] string? DocumentNumber, - DateTime? IssuedAt, - DateTime? ExpiresAt) : IRequest; diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Commands/CreateMerchantCategoryCommand.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Commands/CreateMerchantCategoryCommand.cs deleted file mode 100644 index fe01142..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Commands/CreateMerchantCategoryCommand.cs +++ /dev/null @@ -1,13 +0,0 @@ -using MediatR; -using System.ComponentModel.DataAnnotations; -using TakeoutSaaS.Application.App.Merchants.Dto; - -namespace TakeoutSaaS.Application.App.Merchants.Commands; - -/// -/// 新增商户类目。 -/// -public sealed record CreateMerchantCategoryCommand( - [property: Required, MaxLength(64)] string Name, - int? DisplayOrder, - bool IsActive = true) : IRequest; diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Commands/CreateMerchantCommand.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Commands/CreateMerchantCommand.cs deleted file mode 100644 index ba98a8c..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Commands/CreateMerchantCommand.cs +++ /dev/null @@ -1,53 +0,0 @@ -using MediatR; -using System.ComponentModel.DataAnnotations; -using TakeoutSaaS.Application.App.Merchants.Dto; -using TakeoutSaaS.Domain.Merchants.Enums; - -namespace TakeoutSaaS.Application.App.Merchants.Commands; - -/// -/// 创建商户命令。 -/// -public sealed class CreateMerchantCommand : IRequest -{ - /// - /// 品牌名称。 - /// - [Required, MaxLength(128)] - public string BrandName { get; init; } = string.Empty; - - /// - /// 品牌简称。 - /// - [MaxLength(64)] - public string? BrandAlias { get; init; } - - /// - /// 品牌 Logo。 - /// - [MaxLength(256)] - public string? LogoUrl { get; init; } - - /// - /// 品类。 - /// - [MaxLength(64)] - public string? Category { get; init; } - - /// - /// 联系电话。 - /// - [Required, MaxLength(32)] - public string ContactPhone { get; init; } = string.Empty; - - /// - /// 联系邮箱。 - /// - [MaxLength(128)] - public string? ContactEmail { get; init; } - - /// - /// 状态,可用于直接设为审核通过等场景。 - /// - public MerchantStatus Status { get; init; } = MerchantStatus.Pending; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Commands/CreateMerchantContractCommand.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Commands/CreateMerchantContractCommand.cs deleted file mode 100644 index 957ba01..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Commands/CreateMerchantContractCommand.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using System.ComponentModel.DataAnnotations; -using TakeoutSaaS.Application.App.Merchants.Dto; - -namespace TakeoutSaaS.Application.App.Merchants.Commands; - -/// -/// 新建商户合同。 -/// -public sealed record CreateMerchantContractCommand( - [property: Required] long MerchantId, - [property: Required, MaxLength(64)] string ContractNumber, - DateTime StartDate, - DateTime EndDate, - [property: Required, MaxLength(512)] string FileUrl) : IRequest; diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Commands/DeleteMerchantCategoryCommand.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Commands/DeleteMerchantCategoryCommand.cs deleted file mode 100644 index 98cfd21..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Commands/DeleteMerchantCategoryCommand.cs +++ /dev/null @@ -1,9 +0,0 @@ -using MediatR; -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Application.App.Merchants.Commands; - -/// -/// 删除商户类目。 -/// -public sealed record DeleteMerchantCategoryCommand([property: Required] long CategoryId) : IRequest; diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Commands/DeleteMerchantCommand.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Commands/DeleteMerchantCommand.cs deleted file mode 100644 index 415665c..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Commands/DeleteMerchantCommand.cs +++ /dev/null @@ -1,14 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.App.Merchants.Commands; - -/// -/// 删除商户命令。 -/// -public sealed class DeleteMerchantCommand : IRequest -{ - /// - /// 商户 ID。 - /// - public long MerchantId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Commands/ReorderMerchantCategoriesCommand.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Commands/ReorderMerchantCategoriesCommand.cs deleted file mode 100644 index 542e6aa..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Commands/ReorderMerchantCategoriesCommand.cs +++ /dev/null @@ -1,17 +0,0 @@ -using MediatR; -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Application.App.Merchants.Commands; - -/// -/// 调整类目排序。 -/// -public sealed record ReorderMerchantCategoriesCommand( - [property: Required, MinLength(1)] IReadOnlyList Items) : IRequest; - -/// -/// 类目排序条目。 -/// -public sealed record MerchantCategoryOrderItem( - [property: Required] long CategoryId, - [property: Range(-1000, 100000)] int DisplayOrder); diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Commands/UpdateMerchantCommand.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Commands/UpdateMerchantCommand.cs deleted file mode 100644 index a140562..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Commands/UpdateMerchantCommand.cs +++ /dev/null @@ -1,50 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Dto; - -namespace TakeoutSaaS.Application.App.Merchants.Commands; - -/// -/// 更新商户命令。 -/// -public sealed record UpdateMerchantCommand : IRequest -{ - /// - /// 商户 ID。 - /// - public long MerchantId { get; init; } - - /// - /// 商户名称。 - /// - public string? Name { get; init; } - - /// - /// 营业执照号。 - /// - public string? LicenseNumber { get; init; } - - /// - /// 法人或负责人。 - /// - public string? LegalRepresentative { get; init; } - - /// - /// 注册地址。 - /// - public string? RegisteredAddress { get; init; } - - /// - /// 联系电话。 - /// - public string? ContactPhone { get; init; } - - /// - /// 联系邮箱。 - /// - public string? ContactEmail { get; init; } - - /// - /// 并发控制版本(兼容字段,当前由数据库 xmin 托管)。 - /// - public byte[]? RowVersion { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Commands/UpdateMerchantContractStatusCommand.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Commands/UpdateMerchantContractStatusCommand.cs deleted file mode 100644 index f89f9bf..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Commands/UpdateMerchantContractStatusCommand.cs +++ /dev/null @@ -1,16 +0,0 @@ -using MediatR; -using System.ComponentModel.DataAnnotations; -using TakeoutSaaS.Application.App.Merchants.Dto; -using TakeoutSaaS.Domain.Merchants.Enums; - -namespace TakeoutSaaS.Application.App.Merchants.Commands; - -/// -/// 更新合同状态。 -/// -public sealed record UpdateMerchantContractStatusCommand( - [property: Required] long MerchantId, - [property: Required] long ContractId, - [property: Required] ContractStatus Status, - DateTime? SignedAt, - string? Reason) : IRequest; diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/AddMerchantDocumentCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/AddMerchantDocumentCommandHandler.cs deleted file mode 100644 index 1ca8cf1..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/AddMerchantDocumentCommandHandler.cs +++ /dev/null @@ -1,81 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Commands; -using TakeoutSaaS.Application.App.Merchants.Dto; -using TakeoutSaaS.Domain.Merchants.Entities; -using TakeoutSaaS.Domain.Merchants.Enums; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Ids; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Merchants.Handlers; - -/// -/// 处理证照上传。 -/// -public sealed class AddMerchantDocumentCommandHandler( - IMerchantRepository merchantRepository, - ITenantProvider tenantProvider, - IIdGenerator idGenerator, - ICurrentUserAccessor currentUserAccessor) - : IRequestHandler -{ - /// - /// 处理上传商户证照请求。 - /// - /// 上传命令。 - /// 取消标记。 - /// 证照 DTO。 - public async Task Handle(AddMerchantDocumentCommand request, CancellationToken cancellationToken) - { - // 1. 获取租户并查询商户 - var tenantId = tenantProvider.GetCurrentTenantId(); - var merchant = await merchantRepository.FindByIdAsync(request.MerchantId, tenantId, cancellationToken) - ?? throw new BusinessException(ErrorCodes.NotFound, "商户不存在"); - - // 2. 构建证照记录 - var document = new MerchantDocument - { - Id = idGenerator.NextId(), - MerchantId = merchant.Id, - DocumentType = request.DocumentType, - Status = MerchantDocumentStatus.Pending, - FileUrl = request.FileUrl.Trim(), - DocumentNumber = request.DocumentNumber?.Trim(), - IssuedAt = request.IssuedAt, - ExpiresAt = request.ExpiresAt - }; - - // 3. 持久化与审计 - await merchantRepository.AddDocumentAsync(document, cancellationToken); - await merchantRepository.AddAuditLogAsync(new MerchantAuditLog - { - TenantId = tenantId, - MerchantId = merchant.Id, - Action = MerchantAuditAction.DocumentUploaded, - Title = "上传证照", - Description = $"类型:{request.DocumentType}", - OperatorId = ResolveOperatorId(), - OperatorName = ResolveOperatorName() - }, cancellationToken); - - await merchantRepository.SaveChangesAsync(cancellationToken); - - // 4. 返回 DTO - return MerchantMapping.ToDto(document); - } - - private long? ResolveOperatorId() - { - var id = currentUserAccessor.UserId; - return id == 0 ? null : id; - } - - private string ResolveOperatorName() - { - var id = currentUserAccessor.UserId; - return id == 0 ? "system" : $"user:{id}"; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/CreateMerchantCategoryCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/CreateMerchantCategoryCommandHandler.cs deleted file mode 100644 index 917bfaa..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/CreateMerchantCategoryCommandHandler.cs +++ /dev/null @@ -1,56 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Commands; -using TakeoutSaaS.Application.App.Merchants.Dto; -using TakeoutSaaS.Domain.Merchants.Entities; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Merchants.Handlers; - -/// -/// 创建类目处理器。 -/// -public sealed class CreateMerchantCategoryCommandHandler( - IMerchantCategoryRepository categoryRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - /// 处理创建商户类目请求。 - /// - /// 创建命令。 - /// 取消标记。 - /// 类目 DTO。 - public async Task Handle(CreateMerchantCategoryCommand request, CancellationToken cancellationToken) - { - // 1. 获取租户上下文 - var tenantId = tenantProvider.GetCurrentTenantId(); - var normalizedName = request.Name.Trim(); - - // 2. 检查重名 - if (await categoryRepository.ExistsAsync(normalizedName, tenantId, cancellationToken)) - { - throw new BusinessException(ErrorCodes.Conflict, $"类目“{normalizedName}”已存在"); - } - - // 3. 计算排序 - var categories = await categoryRepository.ListAsync(tenantId, cancellationToken); - var targetOrder = request.DisplayOrder ?? (categories.Count == 0 ? 1 : categories.Max(x => x.DisplayOrder) + 1); - - // 4. 构建实体 - var entity = new MerchantCategory - { - Name = normalizedName, - DisplayOrder = targetOrder, - IsActive = request.IsActive - }; - - // 5. 持久化并返回 - await categoryRepository.AddAsync(entity, cancellationToken); - await categoryRepository.SaveChangesAsync(cancellationToken); - - return MerchantMapping.ToDto(entity); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/CreateMerchantCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/CreateMerchantCommandHandler.cs deleted file mode 100644 index d6a52e0..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/CreateMerchantCommandHandler.cs +++ /dev/null @@ -1,57 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using System.Security.Cryptography; -using TakeoutSaaS.Application.App.Merchants.Commands; -using TakeoutSaaS.Application.App.Merchants.Dto; -using TakeoutSaaS.Domain.Merchants.Entities; -using TakeoutSaaS.Domain.Merchants.Repositories; - -namespace TakeoutSaaS.Application.App.Merchants.Handlers; - -/// -/// 创建商户命令处理器。 -/// -public sealed class CreateMerchantCommandHandler(IMerchantRepository merchantRepository, ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(CreateMerchantCommand request, CancellationToken cancellationToken) - { - // 1. 构建商户实体 - var merchant = new Merchant - { - BrandName = request.BrandName.Trim(), - BrandAlias = request.BrandAlias?.Trim(), - LogoUrl = request.LogoUrl?.Trim(), - Category = request.Category?.Trim(), - ContactPhone = request.ContactPhone.Trim(), - ContactEmail = request.ContactEmail?.Trim(), - Status = request.Status, - RowVersion = RandomNumberGenerator.GetBytes(16), - JoinedAt = DateTime.UtcNow - }; - - // 2. 持久化 - await merchantRepository.AddMerchantAsync(merchant, cancellationToken); - await merchantRepository.SaveChangesAsync(cancellationToken); - - // 3. 记录日志 - logger.LogInformation("创建商户 {MerchantId} - {BrandName}", merchant.Id, merchant.BrandName); - return MapToDto(merchant); - } - - private static MerchantDto MapToDto(Merchant merchant) => new() - { - Id = merchant.Id, - TenantId = merchant.TenantId, - BrandName = merchant.BrandName, - BrandAlias = merchant.BrandAlias, - LogoUrl = merchant.LogoUrl, - Category = merchant.Category, - ContactPhone = merchant.ContactPhone, - ContactEmail = merchant.ContactEmail, - Status = merchant.Status, - JoinedAt = merchant.JoinedAt, - CreatedAt = merchant.CreatedAt - }; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/CreateMerchantContractCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/CreateMerchantContractCommandHandler.cs deleted file mode 100644 index 4d1a658..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/CreateMerchantContractCommandHandler.cs +++ /dev/null @@ -1,85 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Commands; -using TakeoutSaaS.Application.App.Merchants.Dto; -using TakeoutSaaS.Domain.Merchants.Entities; -using TakeoutSaaS.Domain.Merchants.Enums; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Ids; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Merchants.Handlers; - -/// -/// 创建商户合同。 -/// -public sealed class CreateMerchantContractCommandHandler( - IMerchantRepository merchantRepository, - ITenantProvider tenantProvider, - IIdGenerator idGenerator, - ICurrentUserAccessor currentUserAccessor) - : IRequestHandler -{ - /// - /// 处理创建商户合同请求。 - /// - /// 创建命令。 - /// 取消标记。 - /// 合同 DTO。 - public async Task Handle(CreateMerchantContractCommand request, CancellationToken cancellationToken) - { - // 1. 校验时间 - if (request.EndDate <= request.StartDate) - { - throw new BusinessException(ErrorCodes.BadRequest, "合同结束时间必须晚于开始时间"); - } - - // 2. 查询商户 - var tenantId = tenantProvider.GetCurrentTenantId(); - var merchant = await merchantRepository.FindByIdAsync(request.MerchantId, tenantId, cancellationToken) - ?? throw new BusinessException(ErrorCodes.NotFound, "商户不存在"); - - // 3. 构建合同 - var contract = new MerchantContract - { - Id = idGenerator.NextId(), - MerchantId = merchant.Id, - ContractNumber = request.ContractNumber.Trim(), - StartDate = request.StartDate, - EndDate = request.EndDate, - FileUrl = request.FileUrl.Trim() - }; - - // 4. 持久化与审计 - await merchantRepository.AddContractAsync(contract, cancellationToken); - await merchantRepository.AddAuditLogAsync(new MerchantAuditLog - { - TenantId = tenantId, - MerchantId = merchant.Id, - Action = MerchantAuditAction.ContractUpdated, - Title = "新增合同", - Description = $"合同号:{contract.ContractNumber}", - OperatorId = ResolveOperatorId(), - OperatorName = ResolveOperatorName() - }, cancellationToken); - - await merchantRepository.SaveChangesAsync(cancellationToken); - - // 5. 返回 DTO - return MerchantMapping.ToDto(contract); - } - - private long? ResolveOperatorId() - { - var id = currentUserAccessor.UserId; - return id == 0 ? null : id; - } - - private string ResolveOperatorName() - { - var id = currentUserAccessor.UserId; - return id == 0 ? "system" : $"user:{id}"; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/DeleteMerchantCategoryCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/DeleteMerchantCategoryCommandHandler.cs deleted file mode 100644 index 316214e..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/DeleteMerchantCategoryCommandHandler.cs +++ /dev/null @@ -1,38 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Commands; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Merchants.Handlers; - -/// -/// 删除类目处理器。 -/// -public sealed class DeleteMerchantCategoryCommandHandler( - IMerchantCategoryRepository categoryRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - /// 处理删除类目请求。 - /// - /// 删除命令。 - /// 取消标记。 - /// 执行结果。 - public async Task Handle(DeleteMerchantCategoryCommand request, CancellationToken cancellationToken) - { - // 1. 获取租户上下文 - var tenantId = tenantProvider.GetCurrentTenantId(); - var existing = await categoryRepository.FindByIdAsync(request.CategoryId, tenantId, cancellationToken); - - if (existing == null) - { - return false; - } - - // 2. 删除并保存 - await categoryRepository.RemoveAsync(existing, cancellationToken); - await categoryRepository.SaveChangesAsync(cancellationToken); - return true; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/DeleteMerchantCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/DeleteMerchantCommandHandler.cs deleted file mode 100644 index c79f74f..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/DeleteMerchantCommandHandler.cs +++ /dev/null @@ -1,36 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Merchants.Commands; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Merchants.Handlers; - -/// -/// 删除商户命令处理器。 -/// -public sealed class DeleteMerchantCommandHandler( - IMerchantRepository merchantRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(DeleteMerchantCommand request, CancellationToken cancellationToken) - { - // 1. 校验存在性 - var tenantId = tenantProvider.GetCurrentTenantId(); - var existing = await merchantRepository.FindByIdAsync(request.MerchantId, tenantId, cancellationToken); - if (existing == null) - { - return false; - } - - // 2. 删除 - await merchantRepository.DeleteMerchantAsync(request.MerchantId, tenantId, cancellationToken); - await merchantRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("删除商户 {MerchantId}", request.MerchantId); - - return true; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/ExportMerchantPdfQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/ExportMerchantPdfQueryHandler.cs deleted file mode 100644 index 13d2252..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/ExportMerchantPdfQueryHandler.cs +++ /dev/null @@ -1,40 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Queries; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Domain.Merchants.Services; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Merchants.Handlers; - -/// -/// 导出商户 PDF 处理器。 -/// -public sealed class ExportMerchantPdfQueryHandler( - IMerchantRepository merchantRepository, - IStoreRepository storeRepository, - ITenantRepository tenantRepository, - IMerchantExportService exportService, - ITenantProvider tenantProvider) - : IRequestHandler -{ - public async Task Handle(ExportMerchantPdfQuery request, CancellationToken cancellationToken) - { - var currentTenantId = tenantProvider.GetCurrentTenantId(); - var merchant = await merchantRepository.FindByIdAsync(request.MerchantId, currentTenantId, cancellationToken); - - if (merchant == null) - { - throw new BusinessException(ErrorCodes.NotFound, "商户不存在"); - } - - var stores = await storeRepository.GetByMerchantIdAsync(merchant.Id, merchant.TenantId, cancellationToken); - var auditLogs = await merchantRepository.GetAuditLogsAsync(merchant.Id, merchant.TenantId, cancellationToken); - var tenant = await tenantRepository.FindByIdAsync(merchant.TenantId, cancellationToken); - - return await exportService.ExportToPdfAsync(merchant, tenant?.Name, stores, auditLogs, cancellationToken); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantAuditHistoryQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantAuditHistoryQueryHandler.cs deleted file mode 100644 index 3423417..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantAuditHistoryQueryHandler.cs +++ /dev/null @@ -1,35 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Dto; -using TakeoutSaaS.Application.App.Merchants.Queries; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Merchants.Handlers; - -/// -/// 商户审核历史处理器。 -/// -public sealed class GetMerchantAuditHistoryQueryHandler( - IMerchantRepository merchantRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - /// - public async Task> Handle( - GetMerchantAuditHistoryQuery request, - CancellationToken cancellationToken) - { - var currentTenantId = tenantProvider.GetCurrentTenantId(); - var merchant = await merchantRepository.FindByIdAsync(request.MerchantId, currentTenantId, cancellationToken); - - if (merchant == null) - { - throw new BusinessException(ErrorCodes.NotFound, "商户不存在"); - } - - var logs = await merchantRepository.GetAuditLogsAsync(merchant.Id, merchant.TenantId, cancellationToken); - return logs.Select(MerchantMapping.ToDto).ToList(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantAuditLogsQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantAuditLogsQueryHandler.cs deleted file mode 100644 index c14a842..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantAuditLogsQueryHandler.cs +++ /dev/null @@ -1,41 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Dto; -using TakeoutSaaS.Application.App.Merchants.Queries; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Results; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Merchants.Handlers; - -/// -/// 读取商户审核日志。 -/// -public sealed class GetMerchantAuditLogsQueryHandler( - IMerchantRepository merchantRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - /// - /// 查询商户审核日志列表。 - /// - /// 查询请求。 - /// 取消标记。 - /// 分页结果。 - public async Task> Handle(GetMerchantAuditLogsQuery request, CancellationToken cancellationToken) - { - // 1. 获取租户上下文并查询日志 - var tenantId = tenantProvider.GetCurrentTenantId(); - var logs = await merchantRepository.GetAuditLogsAsync(request.MerchantId, tenantId, cancellationToken); - var total = logs.Count; - - // 2. 分页映射 - var paged = logs - .Skip((request.Page - 1) * request.PageSize) - .Take(request.PageSize) - .Select(MerchantMapping.ToDto) - .ToList(); - - // 3. 返回结果 - return new PagedResult(paged, request.Page, request.PageSize, total); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantByIdQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantByIdQueryHandler.cs deleted file mode 100644 index 8272c6c..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantByIdQueryHandler.cs +++ /dev/null @@ -1,42 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Dto; -using TakeoutSaaS.Application.App.Merchants.Queries; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Merchants.Handlers; - -/// -/// 获取商户详情查询处理器。 -/// -public sealed class GetMerchantByIdQueryHandler(IMerchantRepository merchantRepository, ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - public async Task Handle(GetMerchantByIdQuery request, CancellationToken cancellationToken) - { - // 1. 获取租户上下文 - var tenantId = tenantProvider.GetCurrentTenantId(); - var merchant = await merchantRepository.FindByIdAsync(request.MerchantId, tenantId, cancellationToken); - if (merchant == null) - { - return null; - } - - // 2. 返回 DTO - return new MerchantDto - { - Id = merchant.Id, - TenantId = merchant.TenantId, - BrandName = merchant.BrandName, - BrandAlias = merchant.BrandAlias, - LogoUrl = merchant.LogoUrl, - Category = merchant.Category, - ContactPhone = merchant.ContactPhone, - ContactEmail = merchant.ContactEmail, - Status = merchant.Status, - JoinedAt = merchant.JoinedAt, - CreatedAt = merchant.CreatedAt - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantCategoriesQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantCategoriesQueryHandler.cs deleted file mode 100644 index 4cadf78..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantCategoriesQueryHandler.cs +++ /dev/null @@ -1,37 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Queries; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Merchants.Handlers; - -/// -/// 读取可选类目。 -/// -public sealed class GetMerchantCategoriesQueryHandler( - IMerchantCategoryRepository categoryRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - /// - /// 查询启用的商户类目名称列表。 - /// - /// 查询请求。 - /// 取消标记。 - /// 类目名称集合。 - public async Task> Handle(GetMerchantCategoriesQuery request, CancellationToken cancellationToken) - { - // 1. 获取租户上下文并读取类目 - var tenantId = tenantProvider.GetCurrentTenantId(); - var categories = await categoryRepository.ListAsync(tenantId, cancellationToken); - - // 2. 过滤启用类目并去重 - return categories - .Where(x => x.IsActive) - .Select(x => x.Name.Trim()) - .Where(x => x.Length > 0) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToList() - .AsReadOnly(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantChangeHistoryQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantChangeHistoryQueryHandler.cs deleted file mode 100644 index 7054a62..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantChangeHistoryQueryHandler.cs +++ /dev/null @@ -1,35 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Dto; -using TakeoutSaaS.Application.App.Merchants.Queries; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Merchants.Handlers; - -/// -/// 商户变更历史处理器。 -/// -public sealed class GetMerchantChangeHistoryQueryHandler( - IMerchantRepository merchantRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - /// - public async Task> Handle( - GetMerchantChangeHistoryQuery request, - CancellationToken cancellationToken) - { - var currentTenantId = tenantProvider.GetCurrentTenantId(); - var merchant = await merchantRepository.FindByIdAsync(request.MerchantId, currentTenantId, cancellationToken); - - if (merchant == null) - { - throw new BusinessException(ErrorCodes.NotFound, "商户不存在"); - } - - var logs = await merchantRepository.GetChangeLogsAsync(merchant.Id, merchant.TenantId, request.FieldName, cancellationToken); - return logs.Select(MerchantMapping.ToDto).ToList(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantContractsQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantContractsQueryHandler.cs deleted file mode 100644 index d4aab9d..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantContractsQueryHandler.cs +++ /dev/null @@ -1,36 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Dto; -using TakeoutSaaS.Application.App.Merchants.Queries; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Merchants.Handlers; - -/// -/// 查询合同列表。 -/// -public sealed class GetMerchantContractsQueryHandler( - IMerchantRepository merchantRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - /// - /// 查询商户合同列表。 - /// - /// 查询请求。 - /// 取消标记。 - /// 合同 DTO 列表。 - public async Task> Handle(GetMerchantContractsQuery request, CancellationToken cancellationToken) - { - // 1. 获取租户上下文并校验商户存在 - var tenantId = tenantProvider.GetCurrentTenantId(); - _ = await merchantRepository.FindByIdAsync(request.MerchantId, tenantId, cancellationToken) - ?? throw new BusinessException(ErrorCodes.NotFound, "商户不存在"); - - // 2. 查询合同列表 - var contracts = await merchantRepository.GetContractsAsync(request.MerchantId, tenantId, cancellationToken); - return MerchantMapping.ToContractDtos(contracts); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantDetailQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantDetailQueryHandler.cs deleted file mode 100644 index 236ea6b..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantDetailQueryHandler.cs +++ /dev/null @@ -1,48 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Dto; -using TakeoutSaaS.Application.App.Merchants.Queries; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Merchants.Handlers; - -/// -/// 商户详情处理器。 -/// -public sealed class GetMerchantDetailQueryHandler( - IMerchantRepository merchantRepository, - IStoreRepository storeRepository, - ITenantRepository tenantRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - /// 查询商户详情,包括证照和合同。 - /// - /// 查询请求。 - /// 取消标记。 - /// 商户详情 DTO。 - public async Task Handle(GetMerchantDetailQuery request, CancellationToken cancellationToken) - { - // 1. 获取当前租户并查询商户 - var currentTenantId = tenantProvider.GetCurrentTenantId(); - var merchant = await merchantRepository.FindByIdAsync(request.MerchantId, currentTenantId, cancellationToken); - - if (merchant == null) - { - throw new BusinessException(ErrorCodes.NotFound, "商户不存在"); - } - - // 2. 查询门店与租户信息 - var stores = await storeRepository.GetByMerchantIdAsync(merchant.Id, merchant.TenantId, cancellationToken); - var storeDtos = MerchantMapping.ToStoreDtos(stores); - var tenant = await tenantRepository.FindByIdAsync(merchant.TenantId, cancellationToken); - - // 3. 返回明细 DTO - return MerchantMapping.ToDetailDto(merchant, tenant?.Name, storeDtos); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantDocumentsQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantDocumentsQueryHandler.cs deleted file mode 100644 index df32509..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantDocumentsQueryHandler.cs +++ /dev/null @@ -1,36 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Dto; -using TakeoutSaaS.Application.App.Merchants.Queries; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Merchants.Handlers; - -/// -/// 查询证照列表。 -/// -public sealed class GetMerchantDocumentsQueryHandler( - IMerchantRepository merchantRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - /// - /// 查询商户证照列表。 - /// - /// 查询请求。 - /// 取消标记。 - /// 证照 DTO 列表。 - public async Task> Handle(GetMerchantDocumentsQuery request, CancellationToken cancellationToken) - { - // 1. 获取租户上下文并校验商户存在 - var tenantId = tenantProvider.GetCurrentTenantId(); - _ = await merchantRepository.FindByIdAsync(request.MerchantId, tenantId, cancellationToken) - ?? throw new BusinessException(ErrorCodes.NotFound, "商户不存在"); - - // 2. 查询证照列表 - var documents = await merchantRepository.GetDocumentsAsync(request.MerchantId, tenantId, cancellationToken); - return MerchantMapping.ToDocumentDtos(documents); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantListQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantListQueryHandler.cs deleted file mode 100644 index f56f870..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/GetMerchantListQueryHandler.cs +++ /dev/null @@ -1,98 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Dto; -using TakeoutSaaS.Application.App.Merchants.Queries; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Results; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Merchants.Handlers; - -/// -/// 商户列表查询处理器。 -/// -public sealed class GetMerchantListQueryHandler( - IMerchantRepository merchantRepository, - IStoreRepository storeRepository, - ITenantRepository tenantRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - /// - public async Task> Handle( - GetMerchantListQuery request, - CancellationToken cancellationToken) - { - // 1. 获取当前租户并校验跨租户访问 - var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (request.TenantId.HasValue && request.TenantId.Value != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户查询商户"); - } - - var effectiveTenantId = currentTenantId; - - // 2. 查询商户列表 - var merchants = await merchantRepository.SearchAsync( - effectiveTenantId, - request.Status, - request.OperatingMode, - request.Keyword, - cancellationToken); - - if (merchants.Count == 0) - { - return new PagedResult(Array.Empty(), request.Page, request.PageSize, 0); - } - - // 3. 排序 & 分页 - var sorted = ApplySorting(merchants, request.SortBy, request.SortOrder); - var total = sorted.Count; - var paged = sorted - .Skip((request.Page - 1) * request.PageSize) - .Take(request.PageSize) - .ToList(); - - if (paged.Count == 0) - { - return new PagedResult(Array.Empty(), request.Page, request.PageSize, total); - } - - // 4. 批量查询租户名称 - var tenantIds = paged.Select(x => x.TenantId).Distinct().ToArray(); - var tenants = await tenantRepository.FindByIdsAsync(tenantIds, cancellationToken); - var tenantLookup = tenants.ToDictionary(x => x.Id, x => x.Name); - - // 5. 批量查询门店数量 - var merchantIds = paged.Select(x => x.Id).ToArray(); - var storeCounts = await storeRepository.GetStoreCountsAsync(effectiveTenantId, merchantIds, cancellationToken); - - // 6. 组装 DTO - var items = paged.Select(merchant => - { - var tenantName = tenantLookup.TryGetValue(merchant.TenantId, out var name) ? name : null; - var count = storeCounts.TryGetValue(merchant.Id, out var value) ? value : 0; - return MerchantMapping.ToListItemDto(merchant, tenantName, count); - }).ToList(); - - return new PagedResult(items, request.Page, request.PageSize, total); - } - - private static List ApplySorting( - IReadOnlyList merchants, - string? sortBy, - string? sortOrder) - { - var descending = !string.Equals(sortOrder, "asc", StringComparison.OrdinalIgnoreCase); - return (sortBy ?? string.Empty).Trim().ToLowerInvariant() switch - { - "name" => descending ? merchants.OrderByDescending(x => x.BrandName).ToList() : merchants.OrderBy(x => x.BrandName).ToList(), - "status" => descending ? merchants.OrderByDescending(x => x.Status).ToList() : merchants.OrderBy(x => x.Status).ToList(), - "updatedat" => descending ? merchants.OrderByDescending(x => x.UpdatedAt ?? x.CreatedAt).ToList() : merchants.OrderBy(x => x.UpdatedAt ?? x.CreatedAt).ToList(), - _ => descending ? merchants.OrderByDescending(x => x.CreatedAt).ToList() : merchants.OrderBy(x => x.CreatedAt).ToList() - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/ListMerchantCategoriesQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/ListMerchantCategoriesQueryHandler.cs deleted file mode 100644 index 04c46ac..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/ListMerchantCategoriesQueryHandler.cs +++ /dev/null @@ -1,32 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Dto; -using TakeoutSaaS.Application.App.Merchants.Queries; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Merchants.Handlers; - -/// -/// 列出类目。 -/// -public sealed class ListMerchantCategoriesQueryHandler( - IMerchantCategoryRepository categoryRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - /// - /// 列出所有类目。 - /// - /// 查询请求。 - /// 取消标记。 - /// 类目 DTO 列表。 - public async Task> Handle(ListMerchantCategoriesQuery request, CancellationToken cancellationToken) - { - // 1. 获取租户上下文 - var tenantId = tenantProvider.GetCurrentTenantId(); - var categories = await categoryRepository.ListAsync(tenantId, cancellationToken); - - // 2. 映射 DTO - return MerchantMapping.ToCategoryDtos(categories); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/ReorderMerchantCategoriesCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/ReorderMerchantCategoriesCommandHandler.cs deleted file mode 100644 index acd0242..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/ReorderMerchantCategoriesCommandHandler.cs +++ /dev/null @@ -1,47 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Commands; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Merchants.Handlers; - -/// -/// 类目排序处理器。 -/// -public sealed class ReorderMerchantCategoriesCommandHandler( - IMerchantCategoryRepository categoryRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - /// 调整类目排序。 - /// - /// 排序命令。 - /// 取消标记。 - /// 执行结果。 - public async Task Handle(ReorderMerchantCategoriesCommand request, CancellationToken cancellationToken) - { - // 1. 获取租户并查询类目 - var tenantId = tenantProvider.GetCurrentTenantId(); - var categories = await categoryRepository.ListAsync(tenantId, cancellationToken); - var map = categories.ToDictionary(x => x.Id); - - // 2. 更新排序 - foreach (var item in request.Items) - { - if (!map.TryGetValue(item.CategoryId, out var category)) - { - throw new BusinessException(ErrorCodes.NotFound, $"类目 {item.CategoryId} 不存在"); - } - - category.DisplayOrder = item.DisplayOrder; - } - - // 3. 持久化 - await categoryRepository.UpdateRangeAsync(map.Values, cancellationToken); - await categoryRepository.SaveChangesAsync(cancellationToken); - return true; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/SearchMerchantsQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/SearchMerchantsQueryHandler.cs deleted file mode 100644 index b545129..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/SearchMerchantsQueryHandler.cs +++ /dev/null @@ -1,70 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Dto; -using TakeoutSaaS.Application.App.Merchants.Queries; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Results; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Merchants.Handlers; - -/// -/// 商户列表查询处理器。 -/// -public sealed class SearchMerchantsQueryHandler( - IMerchantRepository merchantRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - /// - public async Task> Handle(SearchMerchantsQuery request, CancellationToken cancellationToken) - { - // 1. 获取租户并查询商户 - var tenantId = tenantProvider.GetCurrentTenantId(); - var merchants = await merchantRepository.SearchAsync(tenantId, request.Status, cancellationToken); - - // 2. 排序与分页 - var sorted = ApplySorting(merchants, request.SortBy, request.SortDescending); - var paged = sorted - .Skip((request.Page - 1) * request.PageSize) - .Take(request.PageSize) - .ToList(); - - // 3. 映射 DTO - var items = paged.Select(merchant => new MerchantDto - { - Id = merchant.Id, - TenantId = merchant.TenantId, - BrandName = merchant.BrandName, - BrandAlias = merchant.BrandAlias, - LogoUrl = merchant.LogoUrl, - Category = merchant.Category, - ContactPhone = merchant.ContactPhone, - ContactEmail = merchant.ContactEmail, - Status = merchant.Status, - JoinedAt = merchant.JoinedAt, - CreatedAt = merchant.CreatedAt - }).ToList(); - - // 4. 返回分页结果 - return new PagedResult(items, request.Page, request.PageSize, merchants.Count); - } - - private static IOrderedEnumerable ApplySorting( - IReadOnlyCollection merchants, - string? sortBy, - bool sortDescending) - { - return sortBy?.ToLowerInvariant() switch - { - "brandname" => sortDescending - ? merchants.OrderByDescending(x => x.BrandName) - : merchants.OrderBy(x => x.BrandName), - "status" => sortDescending - ? merchants.OrderByDescending(x => x.Status) - : merchants.OrderBy(x => x.Status), - _ => sortDescending - ? merchants.OrderByDescending(x => x.CreatedAt) - : merchants.OrderBy(x => x.CreatedAt) - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/UpdateMerchantCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/UpdateMerchantCommandHandler.cs deleted file mode 100644 index 3c76c78..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/UpdateMerchantCommandHandler.cs +++ /dev/null @@ -1,177 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Merchants.Commands; -using TakeoutSaaS.Application.App.Merchants.Dto; -using TakeoutSaaS.Domain.Merchants.Entities; -using TakeoutSaaS.Domain.Merchants.Enums; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Merchants.Handlers; - -/// -/// 更新商户命令处理器。 -/// -public sealed class UpdateMerchantCommandHandler( - IMerchantRepository merchantRepository, - IStoreRepository storeRepository, - ITenantRepository tenantRepository, - ITenantProvider tenantProvider, - ICurrentUserAccessor currentUserAccessor, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(UpdateMerchantCommand request, CancellationToken cancellationToken) - { - // 1. 获取操作者权限 - var currentTenantId = tenantProvider.GetCurrentTenantId(); - - // 2. 读取商户信息 - var merchant = await merchantRepository.GetForUpdateAsync(request.MerchantId, currentTenantId, cancellationToken); - - if (merchant == null) - { - return null; - } - - // 3. 规范化输入 - var name = NormalizeRequired(request.Name, "商户名称"); - var contactPhone = NormalizeRequired(request.ContactPhone, "联系电话"); - var licenseNumber = NormalizeOptional(request.LicenseNumber); - var legalRepresentative = NormalizeOptional(request.LegalRepresentative); - var registeredAddress = NormalizeOptional(request.RegisteredAddress); - var contactEmail = NormalizeOptional(request.ContactEmail); - - var now = DateTime.UtcNow; - var actorId = currentUserAccessor.UserId == 0 ? (long?)null : currentUserAccessor.UserId; - var actorName = ResolveActorName(); - var changes = new List(); - var criticalChanged = false; - - TrackChange("name", merchant.BrandName, name, isCritical: true); - TrackChange("licenseNumber", merchant.BusinessLicenseNumber, licenseNumber, isCritical: true); - TrackChange("legalRepresentative", merchant.LegalPerson, legalRepresentative, isCritical: true); - TrackChange("registeredAddress", merchant.Address, registeredAddress, isCritical: true); - TrackChange("contactPhone", merchant.ContactPhone, contactPhone, isCritical: false); - TrackChange("contactEmail", merchant.ContactEmail, contactEmail, isCritical: false); - - // 4. 写入字段 - merchant.BrandName = name; - merchant.BusinessLicenseNumber = licenseNumber; - merchant.LegalPerson = legalRepresentative; - merchant.Address = registeredAddress; - merchant.ContactPhone = contactPhone; - merchant.ContactEmail = contactEmail; - - var requiresReview = merchant.Status == MerchantStatus.Approved && criticalChanged; - if (requiresReview) - { - merchant.Status = MerchantStatus.Pending; - merchant.IsFrozen = true; - merchant.FrozenReason = "关键信息变更待审核"; - merchant.FrozenAt = now; - } - else if (merchant.Status == MerchantStatus.Rejected) - { - merchant.Status = MerchantStatus.Pending; - merchant.IsFrozen = false; - merchant.FrozenReason = null; - merchant.FrozenAt = null; - } - - // 5. 持久化日志与数据 - await merchantRepository.UpdateMerchantAsync(merchant, cancellationToken); - foreach (var log in changes) - { - await merchantRepository.AddChangeLogAsync(log, cancellationToken); - } - - if (requiresReview) - { - await merchantRepository.AddAuditLogAsync(new MerchantAuditLog - { - TenantId = merchant.TenantId, - MerchantId = merchant.Id, - Action = MerchantAuditAction.ReviewPendingReApproval, - Title = "关键信息变更待审核", - Description = "关键信息修改后已进入待审核状态", - OperatorId = actorId, - OperatorName = actorName - }, cancellationToken); - } - - try - { - await merchantRepository.SaveChangesAsync(cancellationToken); - } - catch (Exception exception) when (IsConcurrencyException(exception)) - { - throw new BusinessException(ErrorCodes.Conflict, "商户信息已被修改,请刷新后重试"); - } - - logger.LogInformation("更新商户 {MerchantId} - {Name}", merchant.Id, merchant.BrandName); - - // 6. 返回更新结果 - var stores = await storeRepository.GetByMerchantIdAsync(merchant.Id, merchant.TenantId, cancellationToken); - var tenant = await tenantRepository.FindByIdAsync(merchant.TenantId, cancellationToken); - var detail = MerchantMapping.ToDetailDto(merchant, tenant?.Name, MerchantMapping.ToStoreDtos(stores)); - - return new UpdateMerchantResultDto - { - Merchant = detail, - RequiresReview = requiresReview - }; - - void TrackChange(string fieldName, string? oldValue, string? newValue, bool isCritical) - { - var normalizedOld = NormalizeOptional(oldValue); - var normalizedNew = NormalizeOptional(newValue); - if (string.Equals(normalizedOld, normalizedNew, StringComparison.Ordinal)) - { - return; - } - - if (isCritical) - { - criticalChanged = true; - } - - changes.Add(new MerchantChangeLog - { - TenantId = merchant.TenantId, - MerchantId = merchant.Id, - FieldName = fieldName, - OldValue = normalizedOld, - NewValue = normalizedNew, - ChangedBy = actorId, - ChangedByName = actorName, - ChangeType = "Update" - }); - } - } - - private static string NormalizeRequired(string? value, string fieldName) - { - if (string.IsNullOrWhiteSpace(value)) - { - throw new BusinessException(ErrorCodes.ValidationFailed, $"{fieldName}不能为空"); - } - - return value.Trim(); - } - - private static string? NormalizeOptional(string? value) - => string.IsNullOrWhiteSpace(value) ? null : value.Trim(); - - private string ResolveActorName() - => currentUserAccessor.IsAuthenticated ? $"user:{currentUserAccessor.UserId}" : "system"; - - private static bool IsConcurrencyException(Exception exception) - => string.Equals(exception.GetType().Name, "DbUpdateConcurrencyException", StringComparison.Ordinal); -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/UpdateMerchantContractStatusCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/UpdateMerchantContractStatusCommandHandler.cs deleted file mode 100644 index 1fc4707..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Handlers/UpdateMerchantContractStatusCommandHandler.cs +++ /dev/null @@ -1,83 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Commands; -using TakeoutSaaS.Application.App.Merchants.Dto; -using TakeoutSaaS.Domain.Merchants.Entities; -using TakeoutSaaS.Domain.Merchants.Enums; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Merchants.Handlers; - -/// -/// 更新合同状态处理器。 -/// -public sealed class UpdateMerchantContractStatusCommandHandler( - IMerchantRepository merchantRepository, - ITenantProvider tenantProvider, - ICurrentUserAccessor currentUserAccessor) - : IRequestHandler -{ - /// - /// 更新合同状态。 - /// - /// 状态变更命令。 - /// 取消标记。 - /// 合同 DTO。 - public async Task Handle(UpdateMerchantContractStatusCommand request, CancellationToken cancellationToken) - { - // 1. 查询合同 - var tenantId = tenantProvider.GetCurrentTenantId(); - var contract = await merchantRepository.FindContractByIdAsync(request.MerchantId, tenantId, request.ContractId, cancellationToken) - ?? throw new BusinessException(ErrorCodes.NotFound, "合同不存在"); - - // 2. 更新状态 - if (request.Status == ContractStatus.Active) - { - contract.Status = ContractStatus.Active; - contract.SignedAt = request.SignedAt ?? DateTime.UtcNow; - } - else if (request.Status == ContractStatus.Terminated) - { - contract.Status = ContractStatus.Terminated; - contract.TerminatedAt = DateTime.UtcNow; - contract.TerminationReason = request.Reason; - } - else - { - contract.Status = request.Status; - } - - // 3. 持久化与审计 - await merchantRepository.UpdateContractAsync(contract, cancellationToken); - await merchantRepository.AddAuditLogAsync(new MerchantAuditLog - { - TenantId = tenantId, - MerchantId = contract.MerchantId, - Action = MerchantAuditAction.ContractStatusChanged, - Title = $"合同状态变更为 {request.Status}", - Description = request.Reason, - OperatorId = ResolveOperatorId(), - OperatorName = ResolveOperatorName() - }, cancellationToken); - - await merchantRepository.SaveChangesAsync(cancellationToken); - - // 4. 返回 DTO - return MerchantMapping.ToDto(contract); - } - - private long? ResolveOperatorId() - { - var id = currentUserAccessor.UserId; - return id == 0 ? null : id; - } - - private string ResolveOperatorName() - { - var id = currentUserAccessor.UserId; - return id == 0 ? "system" : $"user:{id}"; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/ExportMerchantPdfQuery.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/ExportMerchantPdfQuery.cs deleted file mode 100644 index ea009a3..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/ExportMerchantPdfQuery.cs +++ /dev/null @@ -1,8 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.App.Merchants.Queries; - -/// -/// 导出商户 PDF 查询。 -/// -public sealed record ExportMerchantPdfQuery(long MerchantId) : IRequest; diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantAuditHistoryQuery.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantAuditHistoryQuery.cs deleted file mode 100644 index ebbdeda..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantAuditHistoryQuery.cs +++ /dev/null @@ -1,9 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Dto; - -namespace TakeoutSaaS.Application.App.Merchants.Queries; - -/// -/// 商户审核历史查询。 -/// -public sealed record GetMerchantAuditHistoryQuery(long MerchantId) : IRequest>; diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantAuditLogsQuery.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantAuditLogsQuery.cs deleted file mode 100644 index e82a58c..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantAuditLogsQuery.cs +++ /dev/null @@ -1,13 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Dto; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.App.Merchants.Queries; - -/// -/// 商户审核日志查询。 -/// -public sealed record GetMerchantAuditLogsQuery( - long MerchantId, - int Page = 1, - int PageSize = 20) : IRequest>; diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantByIdQuery.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantByIdQuery.cs deleted file mode 100644 index fce904d..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantByIdQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Dto; - -namespace TakeoutSaaS.Application.App.Merchants.Queries; - -/// -/// 按 ID 获取商户。 -/// -public sealed class GetMerchantByIdQuery : IRequest -{ - /// - /// 商户 ID。 - /// - public long MerchantId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantCategoriesQuery.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantCategoriesQuery.cs deleted file mode 100644 index 558bcc6..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantCategoriesQuery.cs +++ /dev/null @@ -1,8 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.App.Merchants.Queries; - -/// -/// 获取商户可选类目。 -/// -public sealed record GetMerchantCategoriesQuery() : IRequest>; diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantChangeHistoryQuery.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantChangeHistoryQuery.cs deleted file mode 100644 index 8e3e5f3..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantChangeHistoryQuery.cs +++ /dev/null @@ -1,10 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Dto; - -namespace TakeoutSaaS.Application.App.Merchants.Queries; - -/// -/// 获取商户变更历史。 -/// -public sealed record GetMerchantChangeHistoryQuery(long MerchantId, string? FieldName = null) - : IRequest>; diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantContractsQuery.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantContractsQuery.cs deleted file mode 100644 index bdf17d6..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantContractsQuery.cs +++ /dev/null @@ -1,9 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Dto; - -namespace TakeoutSaaS.Application.App.Merchants.Queries; - -/// -/// 查询商户合同。 -/// -public sealed record GetMerchantContractsQuery(long MerchantId) : IRequest>; diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantDetailQuery.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantDetailQuery.cs deleted file mode 100644 index f3b3eaa..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantDetailQuery.cs +++ /dev/null @@ -1,9 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Dto; - -namespace TakeoutSaaS.Application.App.Merchants.Queries; - -/// -/// 商户详情查询。 -/// -public sealed record GetMerchantDetailQuery(long MerchantId) : IRequest; diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantDocumentsQuery.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantDocumentsQuery.cs deleted file mode 100644 index f3dd1bf..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantDocumentsQuery.cs +++ /dev/null @@ -1,9 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Dto; - -namespace TakeoutSaaS.Application.App.Merchants.Queries; - -/// -/// 查询商户证照。 -/// -public sealed record GetMerchantDocumentsQuery(long MerchantId) : IRequest>; diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantListQuery.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantListQuery.cs deleted file mode 100644 index ce4dfdc..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/GetMerchantListQuery.cs +++ /dev/null @@ -1,53 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Dto; -using TakeoutSaaS.Domain.Common.Enums; -using TakeoutSaaS.Domain.Merchants.Enums; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.App.Merchants.Queries; - -/// -/// 商户列表查询。 -/// -public sealed class GetMerchantListQuery : IRequest> -{ - /// - /// 关键词(商户名称/营业执照号)。 - /// - public string? Keyword { get; init; } - - /// - /// 状态过滤。 - /// - public MerchantStatus? Status { get; init; } - - /// - /// 经营模式过滤。 - /// - public OperatingMode? OperatingMode { get; init; } - - /// - /// 租户过滤(可选,默认当前租户;禁止跨租户)。 - /// - public long? TenantId { get; init; } - - /// - /// 页码。 - /// - public int Page { get; init; } = 1; - - /// - /// 每页条数。 - /// - public int PageSize { get; init; } = 20; - - /// - /// 排序字段(createdAt/updatedAt/name/status)。 - /// - public string? SortBy { get; init; } - - /// - /// 排序方向(asc/desc)。 - /// - public string? SortOrder { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/ListMerchantCategoriesQuery.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/ListMerchantCategoriesQuery.cs deleted file mode 100644 index 5fa29e9..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/ListMerchantCategoriesQuery.cs +++ /dev/null @@ -1,9 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Dto; - -namespace TakeoutSaaS.Application.App.Merchants.Queries; - -/// -/// 管理端获取完整类目列表。 -/// -public sealed record ListMerchantCategoriesQuery() : IRequest>; diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/SearchMerchantsQuery.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/SearchMerchantsQuery.cs deleted file mode 100644 index b3ca969..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Queries/SearchMerchantsQuery.cs +++ /dev/null @@ -1,37 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Merchants.Dto; -using TakeoutSaaS.Domain.Merchants.Enums; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.App.Merchants.Queries; - -/// -/// 搜索商户列表。 -/// -public sealed class SearchMerchantsQuery : IRequest> -{ - /// - /// 按状态过滤。 - /// - public MerchantStatus? Status { get; init; } - - /// - /// 页码(从 1 开始)。 - /// - public int Page { get; init; } = 1; - - /// - /// 每页条数。 - /// - public int PageSize { get; init; } = 20; - - /// - /// 排序字段(brandName/status/createdAt)。 - /// - public string? SortBy { get; init; } - - /// - /// 是否倒序。 - /// - public bool SortDescending { get; init; } = true; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Validators/CreateMerchantCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Validators/CreateMerchantCommandValidator.cs deleted file mode 100644 index bd930d7..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Validators/CreateMerchantCommandValidator.cs +++ /dev/null @@ -1,23 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Merchants.Commands; - -namespace TakeoutSaaS.Application.App.Merchants.Validators; - -/// -/// 创建商户命令验证器。 -/// -public sealed class CreateMerchantCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public CreateMerchantCommandValidator() - { - RuleFor(x => x.BrandName).NotEmpty().MaximumLength(128); - RuleFor(x => x.BrandAlias).MaximumLength(64); - RuleFor(x => x.LogoUrl).MaximumLength(256); - RuleFor(x => x.Category).MaximumLength(64); - RuleFor(x => x.ContactPhone).NotEmpty().MaximumLength(32); - RuleFor(x => x.ContactEmail).EmailAddress().When(x => !string.IsNullOrWhiteSpace(x.ContactEmail)); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Validators/SearchMerchantsQueryValidator.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Validators/SearchMerchantsQueryValidator.cs deleted file mode 100644 index e14707f..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Validators/SearchMerchantsQueryValidator.cs +++ /dev/null @@ -1,20 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Merchants.Queries; - -namespace TakeoutSaaS.Application.App.Merchants.Validators; - -/// -/// 商户列表查询验证器。 -/// -public sealed class SearchMerchantsQueryValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public SearchMerchantsQueryValidator() - { - RuleFor(x => x.Page).GreaterThan(0); - RuleFor(x => x.PageSize).InclusiveBetween(1, 200); - RuleFor(x => x.SortBy).MaximumLength(64); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Merchants/Validators/UpdateMerchantCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Merchants/Validators/UpdateMerchantCommandValidator.cs deleted file mode 100644 index db43914..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Merchants/Validators/UpdateMerchantCommandValidator.cs +++ /dev/null @@ -1,25 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Merchants.Commands; - -namespace TakeoutSaaS.Application.App.Merchants.Validators; - -/// -/// 更新商户命令验证器。 -/// -public sealed class UpdateMerchantCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public UpdateMerchantCommandValidator() - { - RuleFor(x => x.MerchantId).GreaterThan(0); - RuleFor(x => x.Name).NotEmpty().MaximumLength(128); - RuleFor(x => x.LicenseNumber).MaximumLength(64); - RuleFor(x => x.LegalRepresentative).MaximumLength(64); - RuleFor(x => x.RegisteredAddress).MaximumLength(256); - RuleFor(x => x.ContactPhone).NotEmpty().MaximumLength(32); - RuleFor(x => x.ContactEmail).EmailAddress().MaximumLength(128) - .When(x => !string.IsNullOrWhiteSpace(x.ContactEmail)); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Orders/Commands/CreateOrderCommand.cs b/src/Application/TakeoutSaaS.Application/App/Orders/Commands/CreateOrderCommand.cs deleted file mode 100644 index 824de33..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Orders/Commands/CreateOrderCommand.cs +++ /dev/null @@ -1,117 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Orders.Dto; -using TakeoutSaaS.Domain.Orders.Enums; -using TakeoutSaaS.Domain.Payments.Enums; - -namespace TakeoutSaaS.Application.App.Orders.Commands; - -/// -/// 创建订单命令。 -/// -public sealed class CreateOrderCommand : IRequest -{ - /// - /// 订单号。 - /// - public string OrderNo { get; set; } = string.Empty; - - /// - /// 门店 ID。 - /// - public long StoreId { get; set; } - - /// - /// 渠道。 - /// - public OrderChannel Channel { get; set; } = OrderChannel.MiniProgram; - - /// - /// 履约方式。 - /// - public DeliveryType DeliveryType { get; set; } = DeliveryType.DineIn; - - /// - /// 状态。 - /// - public OrderStatus Status { get; set; } = OrderStatus.PendingPayment; - - /// - /// 支付状态。 - /// - public PaymentStatus PaymentStatus { get; set; } = PaymentStatus.Unpaid; - - /// - /// 顾客姓名。 - /// - public string? CustomerName { get; set; } - - /// - /// 顾客手机号。 - /// - public string? CustomerPhone { get; set; } - - /// - /// 桌号。 - /// - public string? TableNo { get; set; } - - /// - /// 排队号。 - /// - public string? QueueNumber { get; set; } - - /// - /// 预约 ID。 - /// - public long? ReservationId { get; set; } - - /// - /// 商品金额。 - /// - public decimal ItemsAmount { get; set; } - - /// - /// 优惠金额。 - /// - public decimal DiscountAmount { get; set; } - - /// - /// 应付金额。 - /// - public decimal PayableAmount { get; set; } - - /// - /// 实付金额。 - /// - public decimal PaidAmount { get; set; } - - /// - /// 支付时间。 - /// - public DateTime? PaidAt { get; set; } - - /// - /// 完成时间。 - /// - public DateTime? FinishedAt { get; set; } - - /// - /// 取消时间。 - /// - public DateTime? CancelledAt { get; set; } - - /// - /// 取消原因。 - /// - public string? CancelReason { get; set; } - - /// - /// 备注。 - /// - public string? Remark { get; set; } - - /// - /// 明细。 - /// - public IReadOnlyList Items { get; set; } = Array.Empty(); -} diff --git a/src/Application/TakeoutSaaS.Application/App/Orders/Commands/DeleteOrderCommand.cs b/src/Application/TakeoutSaaS.Application/App/Orders/Commands/DeleteOrderCommand.cs deleted file mode 100644 index f7632c6..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Orders/Commands/DeleteOrderCommand.cs +++ /dev/null @@ -1,14 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.App.Orders.Commands; - -/// -/// 删除订单命令。 -/// -public sealed class DeleteOrderCommand : IRequest -{ - /// - /// 订单 ID。 - /// - public long OrderId { get; set; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Orders/Commands/OrderItemRequest.cs b/src/Application/TakeoutSaaS.Application/App/Orders/Commands/OrderItemRequest.cs deleted file mode 100644 index 544cd85..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Orders/Commands/OrderItemRequest.cs +++ /dev/null @@ -1,52 +0,0 @@ -namespace TakeoutSaaS.Application.App.Orders.Commands; - -/// -/// 订单明细请求。 -/// -public sealed class OrderItemRequest -{ - /// - /// 商品 ID。 - /// - public long ProductId { get; set; } - - /// - /// 商品名称。 - /// - public string ProductName { get; set; } = string.Empty; - - /// - /// SKU 描述。 - /// - public string? SkuName { get; set; } - - /// - /// 单位。 - /// - public string? Unit { get; set; } - - /// - /// 数量。 - /// - public int Quantity { get; set; } - - /// - /// 单价。 - /// - public decimal UnitPrice { get; set; } - - /// - /// 折扣金额。 - /// - public decimal DiscountAmount { get; set; } - - /// - /// 小计。 - /// - public decimal SubTotal { get; set; } - - /// - /// 属性 JSON。 - /// - public string? AttributesJson { get; set; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Orders/Commands/UpdateOrderCommand.cs b/src/Application/TakeoutSaaS.Application/App/Orders/Commands/UpdateOrderCommand.cs deleted file mode 100644 index 12de4b7..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Orders/Commands/UpdateOrderCommand.cs +++ /dev/null @@ -1,117 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Orders.Dto; -using TakeoutSaaS.Domain.Orders.Enums; -using TakeoutSaaS.Domain.Payments.Enums; - -namespace TakeoutSaaS.Application.App.Orders.Commands; - -/// -/// 更新订单命令。 -/// -public sealed record UpdateOrderCommand : IRequest -{ - /// - /// 订单 ID。 - /// - public long OrderId { get; init; } - - /// - /// 订单号。 - /// - public string OrderNo { get; init; } = string.Empty; - - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 渠道。 - /// - public OrderChannel Channel { get; init; } = OrderChannel.MiniProgram; - - /// - /// 履约方式。 - /// - public DeliveryType DeliveryType { get; init; } = DeliveryType.DineIn; - - /// - /// 状态。 - /// - public OrderStatus Status { get; init; } = OrderStatus.PendingPayment; - - /// - /// 支付状态。 - /// - public PaymentStatus PaymentStatus { get; init; } = PaymentStatus.Unpaid; - - /// - /// 顾客姓名。 - /// - public string? CustomerName { get; init; } - - /// - /// 顾客手机号。 - /// - public string? CustomerPhone { get; init; } - - /// - /// 桌号。 - /// - public string? TableNo { get; init; } - - /// - /// 排队号。 - /// - public string? QueueNumber { get; init; } - - /// - /// 预约 ID。 - /// - public long? ReservationId { get; init; } - - /// - /// 商品金额。 - /// - public decimal ItemsAmount { get; init; } - - /// - /// 优惠金额。 - /// - public decimal DiscountAmount { get; init; } - - /// - /// 应付金额。 - /// - public decimal PayableAmount { get; init; } - - /// - /// 实付金额。 - /// - public decimal PaidAmount { get; init; } - - /// - /// 支付时间。 - /// - public DateTime? PaidAt { get; init; } - - /// - /// 完成时间。 - /// - public DateTime? FinishedAt { get; init; } - - /// - /// 取消时间。 - /// - public DateTime? CancelledAt { get; init; } - - /// - /// 取消原因。 - /// - public string? CancelReason { get; init; } - - /// - /// 备注。 - /// - public string? Remark { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Orders/Dto/OrderDto.cs b/src/Application/TakeoutSaaS.Application/App/Orders/Dto/OrderDto.cs deleted file mode 100644 index 6add72b..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Orders/Dto/OrderDto.cs +++ /dev/null @@ -1,146 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Orders.Enums; -using TakeoutSaaS.Domain.Payments.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Orders.Dto; - -/// -/// 订单 DTO。 -/// -public sealed class OrderDto -{ - /// - /// 订单 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 租户 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 订单号。 - /// - public string OrderNo { get; init; } = string.Empty; - - /// - /// 门店 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long StoreId { get; init; } - - /// - /// 渠道。 - /// - public OrderChannel Channel { get; init; } - - /// - /// 履约方式。 - /// - public DeliveryType DeliveryType { get; init; } - - /// - /// 状态。 - /// - public OrderStatus Status { get; init; } - - /// - /// 支付状态。 - /// - public PaymentStatus PaymentStatus { get; init; } - - /// - /// 顾客姓名。 - /// - public string? CustomerName { get; init; } - - /// - /// 顾客手机号。 - /// - public string? CustomerPhone { get; init; } - - /// - /// 桌号。 - /// - public string? TableNo { get; init; } - - /// - /// 排队号。 - /// - public string? QueueNumber { get; init; } - - /// - /// 预约 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long? ReservationId { get; init; } - - /// - /// 商品金额。 - /// - public decimal ItemsAmount { get; init; } - - /// - /// 优惠金额。 - /// - public decimal DiscountAmount { get; init; } - - /// - /// 应付金额。 - /// - public decimal PayableAmount { get; init; } - - /// - /// 实付金额。 - /// - public decimal PaidAmount { get; init; } - - /// - /// 支付时间。 - /// - public DateTime? PaidAt { get; init; } - - /// - /// 完成时间。 - /// - public DateTime? FinishedAt { get; init; } - - /// - /// 取消时间。 - /// - public DateTime? CancelledAt { get; init; } - - /// - /// 取消原因。 - /// - public string? CancelReason { get; init; } - - /// - /// 备注。 - /// - public string? Remark { get; init; } - - /// - /// 明细。 - /// - public IReadOnlyList Items { get; init; } = Array.Empty(); - - /// - /// 状态流转。 - /// - public IReadOnlyList StatusHistory { get; init; } = Array.Empty(); - - /// - /// 退款申请。 - /// - public IReadOnlyList Refunds { get; init; } = Array.Empty(); - - /// - /// 创建时间。 - /// - public DateTime CreatedAt { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Orders/Dto/OrderItemDto.cs b/src/Application/TakeoutSaaS.Application/App/Orders/Dto/OrderItemDto.cs deleted file mode 100644 index 6baa720..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Orders/Dto/OrderItemDto.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Orders.Dto; - -/// -/// 订单明细 DTO。 -/// -public sealed class OrderItemDto -{ - /// - /// 明细 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 订单 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long OrderId { get; init; } - - /// - /// 商品 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long ProductId { get; init; } - - /// - /// 商品名称。 - /// - public string ProductName { get; init; } = string.Empty; - - /// - /// SKU 描述。 - /// - public string? SkuName { get; init; } - - /// - /// 单位。 - /// - public string? Unit { get; init; } - - /// - /// 数量。 - /// - public int Quantity { get; init; } - - /// - /// 单价。 - /// - public decimal UnitPrice { get; init; } - - /// - /// 折扣金额。 - /// - public decimal DiscountAmount { get; init; } - - /// - /// 小计。 - /// - public decimal SubTotal { get; init; } - - /// - /// 属性 JSON。 - /// - public string? AttributesJson { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Orders/Dto/OrderStatusHistoryDto.cs b/src/Application/TakeoutSaaS.Application/App/Orders/Dto/OrderStatusHistoryDto.cs deleted file mode 100644 index e62e45e..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Orders/Dto/OrderStatusHistoryDto.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Orders.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Orders.Dto; - -/// -/// 订单状态流转 DTO。 -/// -public sealed class OrderStatusHistoryDto -{ - /// - /// 记录 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 订单 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long OrderId { get; init; } - - /// - /// 状态。 - /// - public OrderStatus Status { get; init; } - - /// - /// 操作人。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long? OperatorId { get; init; } - - /// - /// 备注。 - /// - public string? Notes { get; init; } - - /// - /// 时间。 - /// - public DateTime OccurredAt { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Orders/Dto/RefundRequestDto.cs b/src/Application/TakeoutSaaS.Application/App/Orders/Dto/RefundRequestDto.cs deleted file mode 100644 index d389554..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Orders/Dto/RefundRequestDto.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Orders.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Orders.Dto; - -/// -/// 退款申请 DTO。 -/// -public sealed class RefundRequestDto -{ - /// - /// 退款 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 订单 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long OrderId { get; init; } - - /// - /// 退款单号。 - /// - public string RefundNo { get; init; } = string.Empty; - - /// - /// 金额。 - /// - public decimal Amount { get; init; } - - /// - /// 原因。 - /// - public string Reason { get; init; } = string.Empty; - - /// - /// 状态。 - /// - public RefundStatus Status { get; init; } - - /// - /// 申请时间。 - /// - public DateTime RequestedAt { get; init; } - - /// - /// 处理时间。 - /// - public DateTime? ProcessedAt { get; init; } - - /// - /// 审核备注。 - /// - public string? ReviewNotes { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Orders/Handlers/CreateOrderCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Orders/Handlers/CreateOrderCommandHandler.cs deleted file mode 100644 index 9b3cc0f..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Orders/Handlers/CreateOrderCommandHandler.cs +++ /dev/null @@ -1,156 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Orders.Commands; -using TakeoutSaaS.Application.App.Orders.Dto; -using TakeoutSaaS.Domain.Orders.Entities; -using TakeoutSaaS.Domain.Orders.Repositories; -using TakeoutSaaS.Shared.Abstractions.Ids; - -namespace TakeoutSaaS.Application.App.Orders.Handlers; - -/// -/// 创建订单命令处理器。 -/// -public sealed class CreateOrderCommandHandler( - IOrderRepository orderRepository, - IIdGenerator idGenerator, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(CreateOrderCommand request, CancellationToken cancellationToken) - { - // 1. 构建订单 - var order = new Order - { - Id = idGenerator.NextId(), - OrderNo = request.OrderNo.Trim(), - StoreId = request.StoreId, - Channel = request.Channel, - DeliveryType = request.DeliveryType, - Status = request.Status, - PaymentStatus = request.PaymentStatus, - CustomerName = request.CustomerName?.Trim(), - CustomerPhone = request.CustomerPhone?.Trim(), - TableNo = request.TableNo?.Trim(), - QueueNumber = request.QueueNumber?.Trim(), - ReservationId = request.ReservationId, - ItemsAmount = request.ItemsAmount, - DiscountAmount = request.DiscountAmount, - PayableAmount = request.PayableAmount, - PaidAmount = request.PaidAmount, - PaidAt = request.PaidAt, - FinishedAt = request.FinishedAt, - CancelledAt = request.CancelledAt, - CancelReason = request.CancelReason?.Trim(), - Remark = request.Remark?.Trim() - }; - - // 2. 构建明细 - var items = request.Items.Select(item => new OrderItem - { - OrderId = order.Id, - ProductId = item.ProductId, - ProductName = item.ProductName.Trim(), - SkuName = item.SkuName?.Trim(), - Unit = item.Unit?.Trim(), - Quantity = item.Quantity, - UnitPrice = item.UnitPrice, - DiscountAmount = item.DiscountAmount, - SubTotal = item.SubTotal, - AttributesJson = item.AttributesJson?.Trim() - }).ToList(); - - // 3. 补充金额字段 - if (items.Count > 0) - { - var itemsAmount = items.Sum(x => x.SubTotal); - order.ItemsAmount = itemsAmount; - if (order.PayableAmount <= 0) - { - order.PayableAmount = itemsAmount - order.DiscountAmount; - } - } - - // 4. 持久化 - await orderRepository.AddOrderAsync(order, cancellationToken); - if (items.Count > 0) - { - await orderRepository.AddItemsAsync(items, cancellationToken); - } - - await orderRepository.SaveChangesAsync(cancellationToken); - - // 5. 记录日志 - logger.LogInformation("创建订单 {OrderNo} ({OrderId})", order.OrderNo, order.Id); - - // 6. 返回 DTO - return MapToDto(order, items, [], []); - } - - private static OrderDto MapToDto( - Order order, - IReadOnlyList items, - IReadOnlyList histories, - IReadOnlyList refunds) => new() - { - Id = order.Id, - TenantId = order.TenantId, - OrderNo = order.OrderNo, - StoreId = order.StoreId, - Channel = order.Channel, - DeliveryType = order.DeliveryType, - Status = order.Status, - PaymentStatus = order.PaymentStatus, - CustomerName = order.CustomerName, - CustomerPhone = order.CustomerPhone, - TableNo = order.TableNo, - QueueNumber = order.QueueNumber, - ReservationId = order.ReservationId, - ItemsAmount = order.ItemsAmount, - DiscountAmount = order.DiscountAmount, - PayableAmount = order.PayableAmount, - PaidAmount = order.PaidAmount, - PaidAt = order.PaidAt, - FinishedAt = order.FinishedAt, - CancelledAt = order.CancelledAt, - CancelReason = order.CancelReason, - Remark = order.Remark, - Items = items.Select(x => new OrderItemDto - { - Id = x.Id, - OrderId = x.OrderId, - ProductId = x.ProductId, - ProductName = x.ProductName, - SkuName = x.SkuName, - Unit = x.Unit, - Quantity = x.Quantity, - UnitPrice = x.UnitPrice, - DiscountAmount = x.DiscountAmount, - SubTotal = x.SubTotal, - AttributesJson = x.AttributesJson - }).ToList(), - StatusHistory = histories.Select(x => new OrderStatusHistoryDto - { - Id = x.Id, - OrderId = x.OrderId, - Status = x.Status, - OperatorId = x.OperatorId, - Notes = x.Notes, - OccurredAt = x.OccurredAt - }).ToList(), - Refunds = refunds.Select(x => new RefundRequestDto - { - Id = x.Id, - OrderId = x.OrderId, - RefundNo = x.RefundNo, - Amount = x.Amount, - Reason = x.Reason, - Status = x.Status, - RequestedAt = x.RequestedAt, - ProcessedAt = x.ProcessedAt, - ReviewNotes = x.ReviewNotes - }).ToList(), - CreatedAt = order.CreatedAt - }; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Orders/Handlers/DeleteOrderCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Orders/Handlers/DeleteOrderCommandHandler.cs deleted file mode 100644 index 77e6e95..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Orders/Handlers/DeleteOrderCommandHandler.cs +++ /dev/null @@ -1,39 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Orders.Commands; -using TakeoutSaaS.Domain.Orders.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Orders.Handlers; - -/// -/// 删除订单命令处理器。 -/// -public sealed class DeleteOrderCommandHandler( - IOrderRepository orderRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(DeleteOrderCommand request, CancellationToken cancellationToken) - { - // 1. 校验存在性 - var tenantId = tenantProvider.GetCurrentTenantId(); - var existing = await orderRepository.FindByIdAsync(request.OrderId, tenantId, cancellationToken); - if (existing == null) - { - return false; - } - - // 2. 删除 - await orderRepository.DeleteOrderAsync(request.OrderId, tenantId, cancellationToken); - await orderRepository.SaveChangesAsync(cancellationToken); - - // 3. 记录日志 - logger.LogInformation("删除订单 {OrderId}", request.OrderId); - - // 4. 返回执行结果 - return true; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Orders/Handlers/GetOrderByIdQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Orders/Handlers/GetOrderByIdQueryHandler.cs deleted file mode 100644 index 3a45377..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Orders/Handlers/GetOrderByIdQueryHandler.cs +++ /dev/null @@ -1,105 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Orders.Dto; -using TakeoutSaaS.Application.App.Orders.Queries; -using TakeoutSaaS.Domain.Orders.Entities; -using TakeoutSaaS.Domain.Orders.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Orders.Handlers; - -/// -/// 订单详情查询处理器。 -/// -public sealed class GetOrderByIdQueryHandler( - IOrderRepository orderRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - public async Task Handle(GetOrderByIdQuery request, CancellationToken cancellationToken) - { - // 1. 获取当前租户 - var tenantId = tenantProvider.GetCurrentTenantId(); - - // 2. 查询订单主体 - var order = await orderRepository.FindByIdAsync(request.OrderId, tenantId, cancellationToken); - if (order == null) - { - return null; - } - - // 3. 查询关联明细 - var items = await orderRepository.GetItemsAsync(order.Id, tenantId, cancellationToken); - var histories = await orderRepository.GetStatusHistoryAsync(order.Id, tenantId, cancellationToken); - var refunds = await orderRepository.GetRefundsAsync(order.Id, tenantId, cancellationToken); - - // 4. 映射并返回 - return MapToDto(order, items, histories, refunds); - } - - private static OrderDto MapToDto( - Order order, - IReadOnlyList items, - IReadOnlyList histories, - IReadOnlyList refunds) => new() - { - Id = order.Id, - TenantId = order.TenantId, - OrderNo = order.OrderNo, - StoreId = order.StoreId, - Channel = order.Channel, - DeliveryType = order.DeliveryType, - Status = order.Status, - PaymentStatus = order.PaymentStatus, - CustomerName = order.CustomerName, - CustomerPhone = order.CustomerPhone, - TableNo = order.TableNo, - QueueNumber = order.QueueNumber, - ReservationId = order.ReservationId, - ItemsAmount = order.ItemsAmount, - DiscountAmount = order.DiscountAmount, - PayableAmount = order.PayableAmount, - PaidAmount = order.PaidAmount, - PaidAt = order.PaidAt, - FinishedAt = order.FinishedAt, - CancelledAt = order.CancelledAt, - CancelReason = order.CancelReason, - Remark = order.Remark, - Items = items.Select(x => new OrderItemDto - { - Id = x.Id, - OrderId = x.OrderId, - ProductId = x.ProductId, - ProductName = x.ProductName, - SkuName = x.SkuName, - Unit = x.Unit, - Quantity = x.Quantity, - UnitPrice = x.UnitPrice, - DiscountAmount = x.DiscountAmount, - SubTotal = x.SubTotal, - AttributesJson = x.AttributesJson - }).ToList(), - StatusHistory = histories.Select(x => new OrderStatusHistoryDto - { - Id = x.Id, - OrderId = x.OrderId, - Status = x.Status, - OperatorId = x.OperatorId, - Notes = x.Notes, - OccurredAt = x.OccurredAt - }).ToList(), - Refunds = refunds.Select(x => new RefundRequestDto - { - Id = x.Id, - OrderId = x.OrderId, - RefundNo = x.RefundNo, - Amount = x.Amount, - Reason = x.Reason, - Status = x.Status, - RequestedAt = x.RequestedAt, - ProcessedAt = x.ProcessedAt, - ReviewNotes = x.ReviewNotes - }).ToList(), - CreatedAt = order.CreatedAt - }; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Orders/Handlers/SearchOrdersQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Orders/Handlers/SearchOrdersQueryHandler.cs deleted file mode 100644 index 90844c1..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Orders/Handlers/SearchOrdersQueryHandler.cs +++ /dev/null @@ -1,92 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Orders.Dto; -using TakeoutSaaS.Application.App.Orders.Queries; -using TakeoutSaaS.Domain.Orders.Repositories; -using TakeoutSaaS.Shared.Abstractions.Results; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Orders.Handlers; - -/// -/// 订单列表查询处理器。 -/// -public sealed class SearchOrdersQueryHandler( - IOrderRepository orderRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - /// - public async Task> Handle(SearchOrdersQuery request, CancellationToken cancellationToken) - { - // 1. 获取当前租户并查询订单 - var tenantId = tenantProvider.GetCurrentTenantId(); - var orders = await orderRepository.SearchAsync(tenantId, request.Status, request.PaymentStatus, cancellationToken); - - // 2. 可选过滤:门店 - if (request.StoreId.HasValue) - { - orders = orders.Where(x => x.StoreId == request.StoreId.Value).ToList(); - } - - // 3. 可选过滤:订单号模糊 - if (!string.IsNullOrWhiteSpace(request.OrderNo)) - { - var orderNo = request.OrderNo.Trim(); - orders = orders - .Where(x => x.OrderNo.Contains(orderNo, StringComparison.OrdinalIgnoreCase)) - .ToList(); - } - - // 4. 排序与分页 - var sorted = ApplySorting(orders, request.SortBy, request.SortDescending); - var paged = sorted - .Skip((request.Page - 1) * request.PageSize) - .Take(request.PageSize) - .ToList(); - - // 5. 映射 DTO - var items = paged.Select(order => new OrderDto - { - Id = order.Id, - TenantId = order.TenantId, - OrderNo = order.OrderNo, - StoreId = order.StoreId, - Channel = order.Channel, - DeliveryType = order.DeliveryType, - Status = order.Status, - PaymentStatus = order.PaymentStatus, - CustomerName = order.CustomerName, - CustomerPhone = order.CustomerPhone, - TableNo = order.TableNo, - QueueNumber = order.QueueNumber, - ReservationId = order.ReservationId, - ItemsAmount = order.ItemsAmount, - DiscountAmount = order.DiscountAmount, - PayableAmount = order.PayableAmount, - PaidAmount = order.PaidAmount, - PaidAt = order.PaidAt, - FinishedAt = order.FinishedAt, - CancelledAt = order.CancelledAt, - CancelReason = order.CancelReason, - Remark = order.Remark, - CreatedAt = order.CreatedAt - }).ToList(); - - // 6. 返回分页结果 - return new PagedResult(items, request.Page, request.PageSize, orders.Count); - } - - private static IOrderedEnumerable ApplySorting( - IReadOnlyCollection orders, - string? sortBy, - bool sortDescending) - { - return sortBy?.ToLowerInvariant() switch - { - "paidat" => sortDescending ? orders.OrderByDescending(x => x.PaidAt) : orders.OrderBy(x => x.PaidAt), - "status" => sortDescending ? orders.OrderByDescending(x => x.Status) : orders.OrderBy(x => x.Status), - "payableamount" => sortDescending ? orders.OrderByDescending(x => x.PayableAmount) : orders.OrderBy(x => x.PayableAmount), - _ => sortDescending ? orders.OrderByDescending(x => x.CreatedAt) : orders.OrderBy(x => x.CreatedAt) - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Orders/Handlers/UpdateOrderCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Orders/Handlers/UpdateOrderCommandHandler.cs deleted file mode 100644 index 53f6c88..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Orders/Handlers/UpdateOrderCommandHandler.cs +++ /dev/null @@ -1,133 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Orders.Commands; -using TakeoutSaaS.Application.App.Orders.Dto; -using TakeoutSaaS.Domain.Orders.Entities; -using TakeoutSaaS.Domain.Orders.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Orders.Handlers; - -/// -/// 更新订单命令处理器。 -/// -public sealed class UpdateOrderCommandHandler( - IOrderRepository orderRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(UpdateOrderCommand request, CancellationToken cancellationToken) - { - // 1. 读取订单 - var tenantId = tenantProvider.GetCurrentTenantId(); - var existing = await orderRepository.FindByIdAsync(request.OrderId, tenantId, cancellationToken); - if (existing == null) - { - return null; - } - - // 2. 更新字段 - existing.OrderNo = request.OrderNo.Trim(); - existing.StoreId = request.StoreId; - existing.Channel = request.Channel; - existing.DeliveryType = request.DeliveryType; - existing.Status = request.Status; - existing.PaymentStatus = request.PaymentStatus; - existing.CustomerName = request.CustomerName?.Trim(); - existing.CustomerPhone = request.CustomerPhone?.Trim(); - existing.TableNo = request.TableNo?.Trim(); - existing.QueueNumber = request.QueueNumber?.Trim(); - existing.ReservationId = request.ReservationId; - existing.ItemsAmount = request.ItemsAmount; - existing.DiscountAmount = request.DiscountAmount; - existing.PayableAmount = request.PayableAmount; - existing.PaidAmount = request.PaidAmount; - existing.PaidAt = request.PaidAt; - existing.FinishedAt = request.FinishedAt; - existing.CancelledAt = request.CancelledAt; - existing.CancelReason = request.CancelReason?.Trim(); - existing.Remark = request.Remark?.Trim(); - - // 3. 持久化 - await orderRepository.UpdateOrderAsync(existing, cancellationToken); - await orderRepository.SaveChangesAsync(cancellationToken); - - // 4. 记录更新日志 - logger.LogInformation("更新订单 {OrderNo} ({OrderId})", existing.OrderNo, existing.Id); - - // 5. 读取关联数据并返回 - var items = await orderRepository.GetItemsAsync(existing.Id, tenantId, cancellationToken); - var histories = await orderRepository.GetStatusHistoryAsync(existing.Id, tenantId, cancellationToken); - var refunds = await orderRepository.GetRefundsAsync(existing.Id, tenantId, cancellationToken); - - return MapToDto(existing, items, histories, refunds); - } - - private static OrderDto MapToDto( - Order order, - IReadOnlyList items, - IReadOnlyList histories, - IReadOnlyList refunds) => new() - { - Id = order.Id, - TenantId = order.TenantId, - OrderNo = order.OrderNo, - StoreId = order.StoreId, - Channel = order.Channel, - DeliveryType = order.DeliveryType, - Status = order.Status, - PaymentStatus = order.PaymentStatus, - CustomerName = order.CustomerName, - CustomerPhone = order.CustomerPhone, - TableNo = order.TableNo, - QueueNumber = order.QueueNumber, - ReservationId = order.ReservationId, - ItemsAmount = order.ItemsAmount, - DiscountAmount = order.DiscountAmount, - PayableAmount = order.PayableAmount, - PaidAmount = order.PaidAmount, - PaidAt = order.PaidAt, - FinishedAt = order.FinishedAt, - CancelledAt = order.CancelledAt, - CancelReason = order.CancelReason, - Remark = order.Remark, - Items = items.Select(x => new OrderItemDto - { - Id = x.Id, - OrderId = x.OrderId, - ProductId = x.ProductId, - ProductName = x.ProductName, - SkuName = x.SkuName, - Unit = x.Unit, - Quantity = x.Quantity, - UnitPrice = x.UnitPrice, - DiscountAmount = x.DiscountAmount, - SubTotal = x.SubTotal, - AttributesJson = x.AttributesJson - }).ToList(), - StatusHistory = histories.Select(x => new OrderStatusHistoryDto - { - Id = x.Id, - OrderId = x.OrderId, - Status = x.Status, - OperatorId = x.OperatorId, - Notes = x.Notes, - OccurredAt = x.OccurredAt - }).ToList(), - Refunds = refunds.Select(x => new RefundRequestDto - { - Id = x.Id, - OrderId = x.OrderId, - RefundNo = x.RefundNo, - Amount = x.Amount, - Reason = x.Reason, - Status = x.Status, - RequestedAt = x.RequestedAt, - ProcessedAt = x.ProcessedAt, - ReviewNotes = x.ReviewNotes - }).ToList(), - CreatedAt = order.CreatedAt - }; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Orders/Queries/GetOrderByIdQuery.cs b/src/Application/TakeoutSaaS.Application/App/Orders/Queries/GetOrderByIdQuery.cs deleted file mode 100644 index 1446c27..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Orders/Queries/GetOrderByIdQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Orders.Dto; - -namespace TakeoutSaaS.Application.App.Orders.Queries; - -/// -/// 获取订单详情查询。 -/// -public sealed class GetOrderByIdQuery : IRequest -{ - /// - /// 订单 ID。 - /// - public long OrderId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Orders/Queries/SearchOrdersQuery.cs b/src/Application/TakeoutSaaS.Application/App/Orders/Queries/SearchOrdersQuery.cs deleted file mode 100644 index 74c6753..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Orders/Queries/SearchOrdersQuery.cs +++ /dev/null @@ -1,53 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Orders.Dto; -using TakeoutSaaS.Domain.Orders.Enums; -using TakeoutSaaS.Domain.Payments.Enums; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.App.Orders.Queries; - -/// -/// 订单列表查询。 -/// -public sealed class SearchOrdersQuery : IRequest> -{ - /// - /// 门店 ID(可选)。 - /// - public long? StoreId { get; init; } - - /// - /// 订单状态。 - /// - public OrderStatus? Status { get; init; } - - /// - /// 支付状态。 - /// - public PaymentStatus? PaymentStatus { get; init; } - - /// - /// 订单号(模糊或精确,由调用方控制)。 - /// - public string? OrderNo { get; init; } - - /// - /// 页码。 - /// - public int Page { get; init; } = 1; - - /// - /// 每页条数。 - /// - public int PageSize { get; init; } = 20; - - /// - /// 排序字段(createdAt/paidAt/status/payableAmount)。 - /// - public string? SortBy { get; init; } - - /// - /// 是否倒序。 - /// - public bool SortDescending { get; init; } = true; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Orders/Validators/CreateOrderCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Orders/Validators/CreateOrderCommandValidator.cs deleted file mode 100644 index 60f3d0c..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Orders/Validators/CreateOrderCommandValidator.cs +++ /dev/null @@ -1,79 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Orders.Commands; -using TakeoutSaaS.Domain.Orders.Enums; -using TakeoutSaaS.Domain.Payments.Enums; - -namespace TakeoutSaaS.Application.App.Orders.Validators; - -/// -/// 创建订单命令验证器。 -/// -public sealed class CreateOrderCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public CreateOrderCommandValidator() - { - RuleFor(x => x.OrderNo).NotEmpty().MaximumLength(32); - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.CustomerPhone).MaximumLength(32); - RuleFor(x => x.CustomerName).MaximumLength(64); - RuleFor(x => x.TableNo).MaximumLength(32); - RuleFor(x => x.QueueNumber).MaximumLength(32); - RuleFor(x => x.CancelReason).MaximumLength(256); - RuleFor(x => x.Remark).MaximumLength(512); - RuleFor(x => x.ItemsAmount).GreaterThanOrEqualTo(0); - RuleFor(x => x.DiscountAmount).GreaterThanOrEqualTo(0); - RuleFor(x => x.PayableAmount).GreaterThanOrEqualTo(0); - RuleFor(x => x.PaidAmount).GreaterThanOrEqualTo(0); - RuleFor(x => x.PayableAmount) - .Must((cmd, payable) => payable == cmd.ItemsAmount - cmd.DiscountAmount) - .WithMessage("应付金额必须等于商品金额减去优惠金额"); - RuleFor(x => x.PaidAmount) - .LessThanOrEqualTo(x => x.PayableAmount) - .WithMessage("实付金额不得超过应付金额"); - - RuleFor(x => x.PaymentStatus) - .Must(status => status is PaymentStatus.Unpaid or PaymentStatus.Paying or PaymentStatus.Paid or PaymentStatus.Failed or PaymentStatus.Refunded) - .WithMessage("支付状态不合法"); - When(x => x.PaymentStatus == PaymentStatus.Paid, () => - { - RuleFor(x => x.PaidAt).NotNull().WithMessage("支付成功必须包含支付时间"); - RuleFor(x => x.PaidAmount).GreaterThan(0).WithMessage("支付成功时实付金额必须大于 0"); - }); - When(x => x.PaymentStatus != PaymentStatus.Paid, () => - { - RuleFor(x => x.PaidAt).Must(paidAt => paidAt == null).WithMessage("非支付成功状态不应包含支付时间"); - }); - When(x => x.PaymentStatus == PaymentStatus.Refunded, () => - { - RuleFor(x => x.PaidAmount).GreaterThanOrEqualTo(0).WithMessage("退款状态下实付金额需合法"); - }); - When(x => x.Status == OrderStatus.Cancelled, () => - { - RuleFor(x => x.CancelReason).NotEmpty().WithMessage("取消订单必须提供取消原因"); - }); - When(x => x.Status != OrderStatus.Cancelled, () => - { - RuleFor(x => x.CancelReason).Must(reason => string.IsNullOrWhiteSpace(reason)).WithMessage("非取消状态不应包含取消原因"); - }); - - RuleFor(x => x.Items) - .NotEmpty() - .WithMessage("订单明细不能为空"); - - RuleForEach(x => x.Items).ChildRules(item => - { - item.RuleFor(i => i.ProductId).GreaterThan(0); - item.RuleFor(i => i.ProductName).NotEmpty().MaximumLength(128); - item.RuleFor(i => i.SkuName).MaximumLength(128); - item.RuleFor(i => i.Unit).MaximumLength(16); - item.RuleFor(i => i.Quantity).GreaterThan(0); - item.RuleFor(i => i.UnitPrice).GreaterThanOrEqualTo(0); - item.RuleFor(i => i.DiscountAmount).GreaterThanOrEqualTo(0); - item.RuleFor(i => i.SubTotal).GreaterThanOrEqualTo(0); - item.RuleFor(i => i.AttributesJson).MaximumLength(4000); - }); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Orders/Validators/SearchOrdersQueryValidator.cs b/src/Application/TakeoutSaaS.Application/App/Orders/Validators/SearchOrdersQueryValidator.cs deleted file mode 100644 index b5dac41..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Orders/Validators/SearchOrdersQueryValidator.cs +++ /dev/null @@ -1,21 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Orders.Queries; - -namespace TakeoutSaaS.Application.App.Orders.Validators; - -/// -/// 订单列表查询验证器。 -/// -public sealed class SearchOrdersQueryValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public SearchOrdersQueryValidator() - { - RuleFor(x => x.Page).GreaterThan(0); - RuleFor(x => x.PageSize).InclusiveBetween(1, 200); - RuleFor(x => x.SortBy).MaximumLength(64); - RuleFor(x => x.OrderNo).MaximumLength(32); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Orders/Validators/UpdateOrderCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Orders/Validators/UpdateOrderCommandValidator.cs deleted file mode 100644 index 745f033..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Orders/Validators/UpdateOrderCommandValidator.cs +++ /dev/null @@ -1,63 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Orders.Commands; -using TakeoutSaaS.Domain.Orders.Enums; -using TakeoutSaaS.Domain.Payments.Enums; - -namespace TakeoutSaaS.Application.App.Orders.Validators; - -/// -/// 更新订单命令验证器。 -/// -public sealed class UpdateOrderCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public UpdateOrderCommandValidator() - { - RuleFor(x => x.OrderId).GreaterThan(0); - RuleFor(x => x.OrderNo).NotEmpty().MaximumLength(32); - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.CustomerPhone).MaximumLength(32); - RuleFor(x => x.CustomerName).MaximumLength(64); - RuleFor(x => x.TableNo).MaximumLength(32); - RuleFor(x => x.QueueNumber).MaximumLength(32); - RuleFor(x => x.CancelReason).MaximumLength(256); - RuleFor(x => x.Remark).MaximumLength(512); - RuleFor(x => x.ItemsAmount).GreaterThanOrEqualTo(0); - RuleFor(x => x.DiscountAmount).GreaterThanOrEqualTo(0); - RuleFor(x => x.PayableAmount).GreaterThanOrEqualTo(0); - RuleFor(x => x.PaidAmount).GreaterThanOrEqualTo(0); - RuleFor(x => x.PayableAmount) - .Must((cmd, payable) => payable == cmd.ItemsAmount - cmd.DiscountAmount) - .WithMessage("应付金额必须等于商品金额减去优惠金额"); - RuleFor(x => x.PaidAmount) - .LessThanOrEqualTo(x => x.PayableAmount) - .WithMessage("实付金额不得超过应付金额"); - - RuleFor(x => x.PaymentStatus) - .Must(status => status is PaymentStatus.Unpaid or PaymentStatus.Paying or PaymentStatus.Paid or PaymentStatus.Failed or PaymentStatus.Refunded) - .WithMessage("支付状态不合法"); - When(x => x.PaymentStatus == PaymentStatus.Paid, () => - { - RuleFor(x => x.PaidAt).NotNull().WithMessage("支付成功必须包含支付时间"); - RuleFor(x => x.PaidAmount).GreaterThan(0).WithMessage("支付成功时实付金额必须大于 0"); - }); - When(x => x.PaymentStatus != PaymentStatus.Paid, () => - { - RuleFor(x => x.PaidAt).Must(paidAt => paidAt == null).WithMessage("非支付成功状态不应包含支付时间"); - }); - When(x => x.PaymentStatus == PaymentStatus.Refunded, () => - { - RuleFor(x => x.PaidAmount).GreaterThanOrEqualTo(0).WithMessage("退款状态下实付金额需合法"); - }); - When(x => x.Status == OrderStatus.Cancelled, () => - { - RuleFor(x => x.CancelReason).NotEmpty().WithMessage("取消订单必须提供取消原因"); - }); - When(x => x.Status != OrderStatus.Cancelled, () => - { - RuleFor(x => x.CancelReason).Must(reason => string.IsNullOrWhiteSpace(reason)).WithMessage("非取消状态不应包含取消原因"); - }); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Payments/Commands/CreatePaymentCommand.cs b/src/Application/TakeoutSaaS.Application/App/Payments/Commands/CreatePaymentCommand.cs deleted file mode 100644 index 2d1923a..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Payments/Commands/CreatePaymentCommand.cs +++ /dev/null @@ -1,56 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Payments.Dto; -using TakeoutSaaS.Domain.Payments.Enums; - -namespace TakeoutSaaS.Application.App.Payments.Commands; - -/// -/// 创建支付记录命令。 -/// -public sealed class CreatePaymentCommand : IRequest -{ - /// - /// 订单 ID。 - /// - public long OrderId { get; set; } - - /// - /// 支付方式。 - /// - public PaymentMethod Method { get; set; } = PaymentMethod.Unknown; - - /// - /// 支付状态。 - /// - public PaymentStatus Status { get; set; } = PaymentStatus.Unpaid; - - /// - /// 金额。 - /// - public decimal Amount { get; set; } - - /// - /// 系统交易号。 - /// - public string? TradeNo { get; set; } - - /// - /// 渠道单号。 - /// - public string? ChannelTransactionId { get; set; } - - /// - /// 支付时间。 - /// - public DateTime? PaidAt { get; set; } - - /// - /// 备注。 - /// - public string? Remark { get; set; } - - /// - /// 原始回调。 - /// - public string? Payload { get; set; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Payments/Commands/DeletePaymentCommand.cs b/src/Application/TakeoutSaaS.Application/App/Payments/Commands/DeletePaymentCommand.cs deleted file mode 100644 index 5c42b47..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Payments/Commands/DeletePaymentCommand.cs +++ /dev/null @@ -1,14 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.App.Payments.Commands; - -/// -/// 删除支付记录命令。 -/// -public sealed class DeletePaymentCommand : IRequest -{ - /// - /// 支付记录 ID。 - /// - public long PaymentId { get; set; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Payments/Commands/UpdatePaymentCommand.cs b/src/Application/TakeoutSaaS.Application/App/Payments/Commands/UpdatePaymentCommand.cs deleted file mode 100644 index 1889a10..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Payments/Commands/UpdatePaymentCommand.cs +++ /dev/null @@ -1,61 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Payments.Dto; -using TakeoutSaaS.Domain.Payments.Enums; - -namespace TakeoutSaaS.Application.App.Payments.Commands; - -/// -/// 更新支付记录命令。 -/// -public sealed record UpdatePaymentCommand : IRequest -{ - /// - /// 支付记录 ID。 - /// - public long PaymentId { get; init; } - - /// - /// 订单 ID。 - /// - public long OrderId { get; init; } - - /// - /// 支付方式。 - /// - public PaymentMethod Method { get; init; } = PaymentMethod.Unknown; - - /// - /// 支付状态。 - /// - public PaymentStatus Status { get; init; } = PaymentStatus.Unpaid; - - /// - /// 金额。 - /// - public decimal Amount { get; init; } - - /// - /// 系统交易号。 - /// - public string? TradeNo { get; init; } - - /// - /// 渠道单号。 - /// - public string? ChannelTransactionId { get; init; } - - /// - /// 支付时间。 - /// - public DateTime? PaidAt { get; init; } - - /// - /// 备注。 - /// - public string? Remark { get; init; } - - /// - /// 原始回调。 - /// - public string? Payload { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Payments/Dto/PaymentDto.cs b/src/Application/TakeoutSaaS.Application/App/Payments/Dto/PaymentDto.cs deleted file mode 100644 index 3852df0..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Payments/Dto/PaymentDto.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Payments.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Payments.Dto; - -/// -/// 支付记录 DTO。 -/// -public sealed class PaymentDto -{ - /// - /// 支付记录 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 租户 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 订单 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long OrderId { get; init; } - - /// - /// 支付方式。 - /// - public PaymentMethod Method { get; init; } - - /// - /// 支付状态。 - /// - public PaymentStatus Status { get; init; } - - /// - /// 金额。 - /// - public decimal Amount { get; init; } - - /// - /// 系统交易号。 - /// - public string? TradeNo { get; init; } - - /// - /// 渠道单号。 - /// - public string? ChannelTransactionId { get; init; } - - /// - /// 支付时间。 - /// - public DateTime? PaidAt { get; init; } - - /// - /// 备注。 - /// - public string? Remark { get; init; } - - /// - /// 原始回调。 - /// - public string? Payload { get; init; } - - /// - /// 退款记录。 - /// - public IReadOnlyList Refunds { get; init; } = Array.Empty(); - - /// - /// 创建时间。 - /// - public DateTime CreatedAt { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Payments/Dto/PaymentRefundDto.cs b/src/Application/TakeoutSaaS.Application/App/Payments/Dto/PaymentRefundDto.cs deleted file mode 100644 index 5c9cfa8..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Payments/Dto/PaymentRefundDto.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Payments.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Payments.Dto; - -/// -/// 退款记录 DTO。 -/// -public sealed class PaymentRefundDto -{ - /// - /// 退款记录 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 支付记录 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long PaymentRecordId { get; init; } - - /// - /// 订单 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long OrderId { get; init; } - - /// - /// 金额。 - /// - public decimal Amount { get; init; } - - /// - /// 渠道退款号。 - /// - public string? ChannelRefundId { get; init; } - - /// - /// 状态。 - /// - public PaymentRefundStatus Status { get; init; } - - /// - /// 原始回调。 - /// - public string? Payload { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Payments/Handlers/CreatePaymentCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Payments/Handlers/CreatePaymentCommandHandler.cs deleted file mode 100644 index 793a2a9..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Payments/Handlers/CreatePaymentCommandHandler.cs +++ /dev/null @@ -1,67 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Payments.Commands; -using TakeoutSaaS.Application.App.Payments.Dto; -using TakeoutSaaS.Domain.Payments.Entities; -using TakeoutSaaS.Domain.Payments.Repositories; - -namespace TakeoutSaaS.Application.App.Payments.Handlers; - -/// -/// 创建支付记录命令处理器。 -/// -public sealed class CreatePaymentCommandHandler(IPaymentRepository paymentRepository, ILogger logger) - : IRequestHandler -{ - private readonly IPaymentRepository _paymentRepository = paymentRepository; - private readonly ILogger _logger = logger; - - /// - public async Task Handle(CreatePaymentCommand request, CancellationToken cancellationToken) - { - var payment = new PaymentRecord - { - OrderId = request.OrderId, - Method = request.Method, - Status = request.Status, - Amount = request.Amount, - TradeNo = request.TradeNo?.Trim(), - ChannelTransactionId = request.ChannelTransactionId?.Trim(), - PaidAt = request.PaidAt, - Remark = request.Remark?.Trim(), - Payload = request.Payload - }; - - await _paymentRepository.AddPaymentAsync(payment, cancellationToken); - await _paymentRepository.SaveChangesAsync(cancellationToken); - _logger.LogInformation("创建支付记录 {PaymentId} 对应订单 {OrderId}", payment.Id, payment.OrderId); - - return MapToDto(payment, []); - } - - private static PaymentDto MapToDto(PaymentRecord payment, IReadOnlyList refunds) => new() - { - Id = payment.Id, - TenantId = payment.TenantId, - OrderId = payment.OrderId, - Method = payment.Method, - Status = payment.Status, - Amount = payment.Amount, - TradeNo = payment.TradeNo, - ChannelTransactionId = payment.ChannelTransactionId, - PaidAt = payment.PaidAt, - Remark = payment.Remark, - Payload = payment.Payload, - CreatedAt = payment.CreatedAt, - Refunds = refunds.Select(x => new PaymentRefundDto - { - Id = x.Id, - PaymentRecordId = x.PaymentRecordId, - OrderId = x.OrderId, - Amount = x.Amount, - ChannelRefundId = x.ChannelRefundId, - Status = x.Status, - Payload = x.Payload - }).ToList() - }; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Payments/Handlers/DeletePaymentCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Payments/Handlers/DeletePaymentCommandHandler.cs deleted file mode 100644 index 07b2ca9..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Payments/Handlers/DeletePaymentCommandHandler.cs +++ /dev/null @@ -1,38 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Payments.Commands; -using TakeoutSaaS.Domain.Payments.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Payments.Handlers; - -/// -/// 删除支付记录命令处理器。 -/// -public sealed class DeletePaymentCommandHandler( - IPaymentRepository paymentRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - private readonly IPaymentRepository _paymentRepository = paymentRepository; - private readonly ITenantProvider _tenantProvider = tenantProvider; - private readonly ILogger _logger = logger; - - /// - public async Task Handle(DeletePaymentCommand request, CancellationToken cancellationToken) - { - var tenantId = _tenantProvider.GetCurrentTenantId(); - var existing = await _paymentRepository.FindByIdAsync(request.PaymentId, tenantId, cancellationToken); - if (existing == null) - { - return false; - } - - await _paymentRepository.DeletePaymentAsync(request.PaymentId, tenantId, cancellationToken); - await _paymentRepository.SaveChangesAsync(cancellationToken); - _logger.LogInformation("删除支付记录 {PaymentId}", request.PaymentId); - - return true; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Payments/Handlers/GetPaymentByIdQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Payments/Handlers/GetPaymentByIdQueryHandler.cs deleted file mode 100644 index 8e5db7a..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Payments/Handlers/GetPaymentByIdQueryHandler.cs +++ /dev/null @@ -1,60 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Payments.Dto; -using TakeoutSaaS.Application.App.Payments.Queries; -using TakeoutSaaS.Domain.Payments.Entities; -using TakeoutSaaS.Domain.Payments.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Payments.Handlers; - -/// -/// 支付记录详情查询处理器。 -/// -public sealed class GetPaymentByIdQueryHandler( - IPaymentRepository paymentRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - private readonly IPaymentRepository _paymentRepository = paymentRepository; - private readonly ITenantProvider _tenantProvider = tenantProvider; - - /// - public async Task Handle(GetPaymentByIdQuery request, CancellationToken cancellationToken) - { - var tenantId = _tenantProvider.GetCurrentTenantId(); - var payment = await _paymentRepository.FindByIdAsync(request.PaymentId, tenantId, cancellationToken); - if (payment == null) - { - return null; - } - - var refunds = await _paymentRepository.GetRefundsAsync(payment.Id, tenantId, cancellationToken); - return MapToDto(payment, refunds); - } - - private static PaymentDto MapToDto(PaymentRecord payment, IReadOnlyList refunds) => new() - { - Id = payment.Id, - TenantId = payment.TenantId, - OrderId = payment.OrderId, - Method = payment.Method, - Status = payment.Status, - Amount = payment.Amount, - TradeNo = payment.TradeNo, - ChannelTransactionId = payment.ChannelTransactionId, - PaidAt = payment.PaidAt, - Remark = payment.Remark, - Payload = payment.Payload, - CreatedAt = payment.CreatedAt, - Refunds = refunds.Select(x => new PaymentRefundDto - { - Id = x.Id, - PaymentRecordId = x.PaymentRecordId, - OrderId = x.OrderId, - Amount = x.Amount, - ChannelRefundId = x.ChannelRefundId, - Status = x.Status, - Payload = x.Payload - }).ToList() - }; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Payments/Handlers/SearchPaymentsQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Payments/Handlers/SearchPaymentsQueryHandler.cs deleted file mode 100644 index a265022..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Payments/Handlers/SearchPaymentsQueryHandler.cs +++ /dev/null @@ -1,70 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Payments.Dto; -using TakeoutSaaS.Application.App.Payments.Queries; -using TakeoutSaaS.Domain.Payments.Repositories; -using TakeoutSaaS.Shared.Abstractions.Results; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Payments.Handlers; - -/// -/// 支付记录列表查询处理器。 -/// -public sealed class SearchPaymentsQueryHandler( - IPaymentRepository paymentRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - private readonly IPaymentRepository _paymentRepository = paymentRepository; - private readonly ITenantProvider _tenantProvider = tenantProvider; - - /// - public async Task> Handle(SearchPaymentsQuery request, CancellationToken cancellationToken) - { - var tenantId = _tenantProvider.GetCurrentTenantId(); - var payments = await _paymentRepository.SearchAsync(tenantId, request.Status, cancellationToken); - - if (request.OrderId.HasValue) - { - payments = payments.Where(x => x.OrderId == request.OrderId.Value).ToList(); - } - - var sorted = ApplySorting(payments, request.SortBy, request.SortDescending); - var paged = sorted - .Skip((request.Page - 1) * request.PageSize) - .Take(request.PageSize) - .ToList(); - - var items = paged.Select(payment => new PaymentDto - { - Id = payment.Id, - TenantId = payment.TenantId, - OrderId = payment.OrderId, - Method = payment.Method, - Status = payment.Status, - Amount = payment.Amount, - TradeNo = payment.TradeNo, - ChannelTransactionId = payment.ChannelTransactionId, - PaidAt = payment.PaidAt, - Remark = payment.Remark, - Payload = payment.Payload, - CreatedAt = payment.CreatedAt - }).ToList(); - - return new PagedResult(items, request.Page, request.PageSize, payments.Count); - } - - private static IOrderedEnumerable ApplySorting( - IReadOnlyCollection payments, - string? sortBy, - bool sortDescending) - { - return sortBy?.ToLowerInvariant() switch - { - "paidat" => sortDescending ? payments.OrderByDescending(x => x.PaidAt) : payments.OrderBy(x => x.PaidAt), - "status" => sortDescending ? payments.OrderByDescending(x => x.Status) : payments.OrderBy(x => x.Status), - "amount" => sortDescending ? payments.OrderByDescending(x => x.Amount) : payments.OrderBy(x => x.Amount), - _ => sortDescending ? payments.OrderByDescending(x => x.CreatedAt) : payments.OrderBy(x => x.CreatedAt) - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Payments/Handlers/UpdatePaymentCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Payments/Handlers/UpdatePaymentCommandHandler.cs deleted file mode 100644 index e0e9fec..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Payments/Handlers/UpdatePaymentCommandHandler.cs +++ /dev/null @@ -1,77 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Payments.Commands; -using TakeoutSaaS.Application.App.Payments.Dto; -using TakeoutSaaS.Domain.Payments.Entities; -using TakeoutSaaS.Domain.Payments.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Payments.Handlers; - -/// -/// 更新支付记录命令处理器。 -/// -public sealed class UpdatePaymentCommandHandler( - IPaymentRepository paymentRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - private readonly IPaymentRepository _paymentRepository = paymentRepository; - private readonly ITenantProvider _tenantProvider = tenantProvider; - private readonly ILogger _logger = logger; - - /// - public async Task Handle(UpdatePaymentCommand request, CancellationToken cancellationToken) - { - var tenantId = _tenantProvider.GetCurrentTenantId(); - var existing = await _paymentRepository.FindByIdAsync(request.PaymentId, tenantId, cancellationToken); - if (existing == null) - { - return null; - } - - existing.OrderId = request.OrderId; - existing.Method = request.Method; - existing.Status = request.Status; - existing.Amount = request.Amount; - existing.TradeNo = request.TradeNo?.Trim(); - existing.ChannelTransactionId = request.ChannelTransactionId?.Trim(); - existing.PaidAt = request.PaidAt; - existing.Remark = request.Remark?.Trim(); - existing.Payload = request.Payload; - - await _paymentRepository.UpdatePaymentAsync(existing, cancellationToken); - await _paymentRepository.SaveChangesAsync(cancellationToken); - _logger.LogInformation("更新支付记录 {PaymentId}", existing.Id); - - var refunds = await _paymentRepository.GetRefundsAsync(existing.Id, tenantId, cancellationToken); - return MapToDto(existing, refunds); - } - - private static PaymentDto MapToDto(PaymentRecord payment, IReadOnlyList refunds) => new() - { - Id = payment.Id, - TenantId = payment.TenantId, - OrderId = payment.OrderId, - Method = payment.Method, - Status = payment.Status, - Amount = payment.Amount, - TradeNo = payment.TradeNo, - ChannelTransactionId = payment.ChannelTransactionId, - PaidAt = payment.PaidAt, - Remark = payment.Remark, - Payload = payment.Payload, - CreatedAt = payment.CreatedAt, - Refunds = refunds.Select(x => new PaymentRefundDto - { - Id = x.Id, - PaymentRecordId = x.PaymentRecordId, - OrderId = x.OrderId, - Amount = x.Amount, - ChannelRefundId = x.ChannelRefundId, - Status = x.Status, - Payload = x.Payload - }).ToList() - }; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Payments/Queries/GetPaymentByIdQuery.cs b/src/Application/TakeoutSaaS.Application/App/Payments/Queries/GetPaymentByIdQuery.cs deleted file mode 100644 index 3ca6c8c..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Payments/Queries/GetPaymentByIdQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Payments.Dto; - -namespace TakeoutSaaS.Application.App.Payments.Queries; - -/// -/// 获取支付记录详情。 -/// -public sealed class GetPaymentByIdQuery : IRequest -{ - /// - /// 支付记录 ID。 - /// - public long PaymentId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Payments/Queries/SearchPaymentsQuery.cs b/src/Application/TakeoutSaaS.Application/App/Payments/Queries/SearchPaymentsQuery.cs deleted file mode 100644 index 2fbf13f..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Payments/Queries/SearchPaymentsQuery.cs +++ /dev/null @@ -1,42 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Payments.Dto; -using TakeoutSaaS.Domain.Payments.Enums; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.App.Payments.Queries; - -/// -/// 支付记录列表查询。 -/// -public sealed class SearchPaymentsQuery : IRequest> -{ - /// - /// 订单 ID(可选)。 - /// - public long? OrderId { get; init; } - - /// - /// 支付状态。 - /// - public PaymentStatus? Status { get; init; } - - /// - /// 页码。 - /// - public int Page { get; init; } = 1; - - /// - /// 每页条数。 - /// - public int PageSize { get; init; } = 20; - - /// - /// 排序字段(createdAt/paidAt/status/amount)。 - /// - public string? SortBy { get; init; } - - /// - /// 是否倒序。 - /// - public bool SortDescending { get; init; } = true; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Payments/Validators/CreatePaymentCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Payments/Validators/CreatePaymentCommandValidator.cs deleted file mode 100644 index 5041e1d..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Payments/Validators/CreatePaymentCommandValidator.cs +++ /dev/null @@ -1,45 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Payments.Commands; -using TakeoutSaaS.Domain.Payments.Enums; - -namespace TakeoutSaaS.Application.App.Payments.Validators; - -/// -/// 创建支付记录命令验证器。 -/// -public sealed class CreatePaymentCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public CreatePaymentCommandValidator() - { - RuleFor(x => x.OrderId).GreaterThan(0); - RuleFor(x => x.Amount).GreaterThan(0); - RuleFor(x => x.Method) - .Must(method => method != PaymentMethod.Unknown) - .WithMessage("支付方式不可为空"); - RuleFor(x => x.TradeNo).MaximumLength(64); - RuleFor(x => x.ChannelTransactionId).MaximumLength(64); - RuleFor(x => x.Remark).MaximumLength(256); - - RuleFor(x => x.Status) - .Must(status => status is PaymentStatus.Unpaid or PaymentStatus.Paying or PaymentStatus.Paid or PaymentStatus.Failed or PaymentStatus.Refunded) - .WithMessage("支付状态不合法"); - When(x => x.Status == PaymentStatus.Paid, () => - { - RuleFor(x => x.PaidAt).NotNull().WithMessage("支付成功必须包含支付时间"); - }); - When(x => x.Status != PaymentStatus.Paid, () => - { - RuleFor(x => x.PaidAt).Must(paidAt => paidAt == null).WithMessage("非支付成功状态不应包含支付时间"); - }); - - When(x => x.Method is PaymentMethod.Cash or PaymentMethod.Card or PaymentMethod.Balance, () => - { - RuleFor(x => x.Status) - .Must(status => status is not PaymentStatus.Paying) - .WithMessage("线下/余额支付不允许处于 Paying 状态"); - }); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Payments/Validators/SearchPaymentsQueryValidator.cs b/src/Application/TakeoutSaaS.Application/App/Payments/Validators/SearchPaymentsQueryValidator.cs deleted file mode 100644 index fe7580e..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Payments/Validators/SearchPaymentsQueryValidator.cs +++ /dev/null @@ -1,20 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Payments.Queries; - -namespace TakeoutSaaS.Application.App.Payments.Validators; - -/// -/// 支付记录查询验证器。 -/// -public sealed class SearchPaymentsQueryValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public SearchPaymentsQueryValidator() - { - RuleFor(x => x.Page).GreaterThan(0); - RuleFor(x => x.PageSize).InclusiveBetween(1, 200); - RuleFor(x => x.SortBy).MaximumLength(64); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Payments/Validators/UpdatePaymentCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Payments/Validators/UpdatePaymentCommandValidator.cs deleted file mode 100644 index 65dfd1c..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Payments/Validators/UpdatePaymentCommandValidator.cs +++ /dev/null @@ -1,46 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Payments.Commands; -using TakeoutSaaS.Domain.Payments.Enums; - -namespace TakeoutSaaS.Application.App.Payments.Validators; - -/// -/// 更新支付记录命令验证器。 -/// -public sealed class UpdatePaymentCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public UpdatePaymentCommandValidator() - { - RuleFor(x => x.PaymentId).GreaterThan(0); - RuleFor(x => x.OrderId).GreaterThan(0); - RuleFor(x => x.Amount).GreaterThan(0); - RuleFor(x => x.Method) - .Must(method => method != PaymentMethod.Unknown) - .WithMessage("支付方式不可为空"); - RuleFor(x => x.TradeNo).MaximumLength(64); - RuleFor(x => x.ChannelTransactionId).MaximumLength(64); - RuleFor(x => x.Remark).MaximumLength(256); - - RuleFor(x => x.Status) - .Must(status => status is PaymentStatus.Unpaid or PaymentStatus.Paying or PaymentStatus.Paid or PaymentStatus.Failed or PaymentStatus.Refunded) - .WithMessage("支付状态不合法"); - When(x => x.Status == PaymentStatus.Paid, () => - { - RuleFor(x => x.PaidAt).NotNull().WithMessage("支付成功必须包含支付时间"); - }); - When(x => x.Status != PaymentStatus.Paid, () => - { - RuleFor(x => x.PaidAt).Must(paidAt => paidAt == null).WithMessage("非支付成功状态不应包含支付时间"); - }); - - When(x => x.Method is PaymentMethod.Cash or PaymentMethod.Card or PaymentMethod.Balance, () => - { - RuleFor(x => x.Status) - .Must(status => status is not PaymentStatus.Paying) - .WithMessage("线下/余额支付不允许处于 Paying 状态"); - }); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Commands/CreateProductCommand.cs b/src/Application/TakeoutSaaS.Application/App/Products/Commands/CreateProductCommand.cs deleted file mode 100644 index 50d08c0..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Commands/CreateProductCommand.cs +++ /dev/null @@ -1,101 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Products.Dto; -using TakeoutSaaS.Domain.Products.Enums; - -namespace TakeoutSaaS.Application.App.Products.Commands; - -/// -/// 创建商品命令。 -/// -public sealed class CreateProductCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; set; } - - /// - /// 分类 ID。 - /// - public long CategoryId { get; set; } - - /// - /// 商品编码。 - /// - public string SpuCode { get; set; } = string.Empty; - - /// - /// 名称。 - /// - public string Name { get; set; } = string.Empty; - - /// - /// 副标题。 - /// - public string? Subtitle { get; set; } - - /// - /// 单位。 - /// - public string? Unit { get; set; } - - /// - /// 现价。 - /// - public decimal Price { get; set; } - - /// - /// 原价。 - /// - public decimal? OriginalPrice { get; set; } - - /// - /// 库存数量。 - /// - public int? StockQuantity { get; set; } - - /// - /// 每单限购。 - /// - public int? MaxQuantityPerOrder { get; set; } - - /// - /// 状态。 - /// - public ProductStatus Status { get; set; } = ProductStatus.Draft; - - /// - /// 主图。 - /// - public string? CoverImage { get; set; } - - /// - /// 图集。 - /// - public string? GalleryImages { get; set; } - - /// - /// 描述。 - /// - public string? Description { get; set; } - - /// - /// 支持堂食。 - /// - public bool EnableDineIn { get; set; } = true; - - /// - /// 支持自提。 - /// - public bool EnablePickup { get; set; } = true; - - /// - /// 支持配送。 - /// - public bool EnableDelivery { get; set; } = true; - - /// - /// 是否推荐。 - /// - public bool IsFeatured { get; set; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Commands/DeleteProductCommand.cs b/src/Application/TakeoutSaaS.Application/App/Products/Commands/DeleteProductCommand.cs deleted file mode 100644 index 9a17c86..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Commands/DeleteProductCommand.cs +++ /dev/null @@ -1,14 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.App.Products.Commands; - -/// -/// 删除商品命令。 -/// -public sealed class DeleteProductCommand : IRequest -{ - /// - /// 商品 ID。 - /// - public long ProductId { get; set; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Commands/PublishProductCommand.cs b/src/Application/TakeoutSaaS.Application/App/Products/Commands/PublishProductCommand.cs deleted file mode 100644 index f8aa134..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Commands/PublishProductCommand.cs +++ /dev/null @@ -1,20 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Products.Dto; - -namespace TakeoutSaaS.Application.App.Products.Commands; - -/// -/// 上架商品命令。 -/// -public sealed record PublishProductCommand : IRequest -{ - /// - /// 商品 ID。 - /// - public long ProductId { get; init; } - - /// - /// 上架备注。 - /// - public string? Reason { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Commands/ReplaceProductAddonsCommand.cs b/src/Application/TakeoutSaaS.Application/App/Products/Commands/ReplaceProductAddonsCommand.cs deleted file mode 100644 index 41ec401..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Commands/ReplaceProductAddonsCommand.cs +++ /dev/null @@ -1,20 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Products.Dto; - -namespace TakeoutSaaS.Application.App.Products.Commands; - -/// -/// 替换商品加料命令。 -/// -public sealed record ReplaceProductAddonsCommand : IRequest> -{ - /// - /// 商品 ID。 - /// - public long ProductId { get; init; } - - /// - /// 加料组。 - /// - public IReadOnlyList AddonGroups { get; init; } = []; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Commands/ReplaceProductAttributesCommand.cs b/src/Application/TakeoutSaaS.Application/App/Products/Commands/ReplaceProductAttributesCommand.cs deleted file mode 100644 index 4ec120f..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Commands/ReplaceProductAttributesCommand.cs +++ /dev/null @@ -1,20 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Products.Dto; - -namespace TakeoutSaaS.Application.App.Products.Commands; - -/// -/// 替换商品规格命令。 -/// -public sealed record ReplaceProductAttributesCommand : IRequest> -{ - /// - /// 商品 ID。 - /// - public long ProductId { get; init; } - - /// - /// 规格组。 - /// - public IReadOnlyList AttributeGroups { get; init; } = []; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Commands/ReplaceProductMediaCommand.cs b/src/Application/TakeoutSaaS.Application/App/Products/Commands/ReplaceProductMediaCommand.cs deleted file mode 100644 index 6e099a0..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Commands/ReplaceProductMediaCommand.cs +++ /dev/null @@ -1,20 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Products.Dto; - -namespace TakeoutSaaS.Application.App.Products.Commands; - -/// -/// 替换商品媒资命令。 -/// -public sealed record ReplaceProductMediaCommand : IRequest> -{ - /// - /// 商品 ID。 - /// - public long ProductId { get; init; } - - /// - /// 媒资列表。 - /// - public IReadOnlyList MediaAssets { get; init; } = []; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Commands/ReplaceProductPricingRulesCommand.cs b/src/Application/TakeoutSaaS.Application/App/Products/Commands/ReplaceProductPricingRulesCommand.cs deleted file mode 100644 index 067b11f..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Commands/ReplaceProductPricingRulesCommand.cs +++ /dev/null @@ -1,20 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Products.Dto; - -namespace TakeoutSaaS.Application.App.Products.Commands; - -/// -/// 替换商品价格策略命令。 -/// -public sealed record ReplaceProductPricingRulesCommand : IRequest> -{ - /// - /// 商品 ID。 - /// - public long ProductId { get; init; } - - /// - /// 价格策略。 - /// - public IReadOnlyList PricingRules { get; init; } = []; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Commands/ReplaceProductSkusCommand.cs b/src/Application/TakeoutSaaS.Application/App/Products/Commands/ReplaceProductSkusCommand.cs deleted file mode 100644 index 8f82fdf..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Commands/ReplaceProductSkusCommand.cs +++ /dev/null @@ -1,20 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Products.Dto; - -namespace TakeoutSaaS.Application.App.Products.Commands; - -/// -/// 替换商品 SKU 命令。 -/// -public sealed record ReplaceProductSkusCommand : IRequest> -{ - /// - /// 商品 ID。 - /// - public long ProductId { get; init; } - - /// - /// SKU 列表。 - /// - public IReadOnlyList Skus { get; init; } = []; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Commands/UnpublishProductCommand.cs b/src/Application/TakeoutSaaS.Application/App/Products/Commands/UnpublishProductCommand.cs deleted file mode 100644 index d59aef5..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Commands/UnpublishProductCommand.cs +++ /dev/null @@ -1,20 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Products.Dto; - -namespace TakeoutSaaS.Application.App.Products.Commands; - -/// -/// 下架商品命令。 -/// -public sealed record UnpublishProductCommand : IRequest -{ - /// - /// 商品 ID。 - /// - public long ProductId { get; init; } - - /// - /// 下架原因。 - /// - public string? Reason { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Commands/UpdateProductCommand.cs b/src/Application/TakeoutSaaS.Application/App/Products/Commands/UpdateProductCommand.cs deleted file mode 100644 index 09cd056..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Commands/UpdateProductCommand.cs +++ /dev/null @@ -1,106 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Products.Dto; -using TakeoutSaaS.Domain.Products.Enums; - -namespace TakeoutSaaS.Application.App.Products.Commands; - -/// -/// 更新商品命令。 -/// -public sealed record UpdateProductCommand : IRequest -{ - /// - /// 商品 ID。 - /// - public long ProductId { get; init; } - - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 分类 ID。 - /// - public long CategoryId { get; init; } - - /// - /// 商品编码。 - /// - public string SpuCode { get; init; } = string.Empty; - - /// - /// 名称。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 副标题。 - /// - public string? Subtitle { get; init; } - - /// - /// 单位。 - /// - public string? Unit { get; init; } - - /// - /// 现价。 - /// - public decimal Price { get; init; } - - /// - /// 原价。 - /// - public decimal? OriginalPrice { get; init; } - - /// - /// 库存数量。 - /// - public int? StockQuantity { get; init; } - - /// - /// 每单限购。 - /// - public int? MaxQuantityPerOrder { get; init; } - - /// - /// 状态。 - /// - public ProductStatus Status { get; init; } = ProductStatus.Draft; - - /// - /// 主图。 - /// - public string? CoverImage { get; init; } - - /// - /// 图集。 - /// - public string? GalleryImages { get; init; } - - /// - /// 描述。 - /// - public string? Description { get; init; } - - /// - /// 支持堂食。 - /// - public bool EnableDineIn { get; init; } = true; - - /// - /// 支持自提。 - /// - public bool EnablePickup { get; init; } = true; - - /// - /// 支持配送。 - /// - public bool EnableDelivery { get; init; } = true; - - /// - /// 是否推荐。 - /// - public bool IsFeatured { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductAddonGroupDto.cs b/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductAddonGroupDto.cs deleted file mode 100644 index c249464..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductAddonGroupDto.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Products.Dto; - -/// -/// 加料组 DTO。 -/// -public sealed record ProductAddonGroupDto -{ - /// - /// 组 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 商品 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long ProductId { get; init; } - - /// - /// 名称。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 最小选择数。 - /// - public int MinSelect { get; init; } - - /// - /// 最大选择数。 - /// - public int MaxSelect { get; init; } - - /// - /// 排序。 - /// - public int SortOrder { get; init; } - - /// - /// 加料选项。 - /// - public IReadOnlyList Options { get; init; } = []; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductAddonOptionDto.cs b/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductAddonOptionDto.cs deleted file mode 100644 index 544ba67..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductAddonOptionDto.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Products.Dto; - -/// -/// 加料选项 DTO。 -/// -public sealed record ProductAddonOptionDto -{ - /// - /// 选项 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 所属加料组 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long AddonGroupId { get; init; } - - /// - /// 名称。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 额外价格。 - /// - public decimal? ExtraPrice { get; init; } - - /// - /// 排序。 - /// - public int SortOrder { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductAttributeGroupDto.cs b/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductAttributeGroupDto.cs deleted file mode 100644 index 7e5ce67..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductAttributeGroupDto.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Products.Dto; - -/// -/// 规格组 DTO。 -/// -public sealed record ProductAttributeGroupDto -{ - /// - /// 组 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 商品 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long ProductId { get; init; } - - /// - /// 名称。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 选择类型。 - /// - public int SelectionType { get; init; } - - /// - /// 排序。 - /// - public int SortOrder { get; init; } - - /// - /// 规格选项。 - /// - public IReadOnlyList Options { get; init; } = []; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductAttributeOptionDto.cs b/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductAttributeOptionDto.cs deleted file mode 100644 index f9fc8ce..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductAttributeOptionDto.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Products.Dto; - -/// -/// 规格选项 DTO。 -/// -public sealed record ProductAttributeOptionDto -{ - /// - /// 选项 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 规格组 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long AttributeGroupId { get; init; } - - /// - /// 名称。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 排序。 - /// - public int SortOrder { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductCategoryMenuDto.cs b/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductCategoryMenuDto.cs deleted file mode 100644 index d758957..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductCategoryMenuDto.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.Collections.Generic; -using System.Text.Json.Serialization; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Products.Dto; - -/// -/// 门店菜单分类 DTO。 -/// -public sealed record ProductCategoryMenuDto -{ - /// - /// 分类 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 门店 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long StoreId { get; init; } - - /// - /// 分类名称。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 分类描述。 - /// - public string? Description { get; init; } - - /// - /// 排序。 - /// - public int SortOrder { get; init; } - - /// - /// 是否启用。 - /// - public bool IsEnabled { get; init; } - - /// - /// 分类下商品列表。 - /// - public IReadOnlyList Products { get; init; } = []; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductDetailDto.cs b/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductDetailDto.cs deleted file mode 100644 index cc9ec59..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductDetailDto.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Text.Json.Serialization; - -namespace TakeoutSaaS.Application.App.Products.Dto; - -/// -/// 商品全量详情 DTO。 -/// -public sealed record ProductDetailDto -{ - /// - /// SPU 基础信息。 - /// - public ProductDto Product { get; init; } = new(); - - /// - /// SKU 列表。 - /// - public IReadOnlyList Skus { get; init; } = []; - - /// - /// 规格组与选项。 - /// - public IReadOnlyList AttributeGroups { get; init; } = []; - - /// - /// 加料组与选项。 - /// - public IReadOnlyList AddonGroups { get; init; } = []; - - /// - /// 价格策略。 - /// - public IReadOnlyList PricingRules { get; init; } = []; - - /// - /// 媒资列表。 - /// - public IReadOnlyList MediaAssets { get; init; } = []; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductDto.cs b/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductDto.cs deleted file mode 100644 index 27adb83..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductDto.cs +++ /dev/null @@ -1,120 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Products.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Products.Dto; - -/// -/// 商品 DTO(含 SPU 基础信息)。 -/// -public sealed class ProductDto -{ - /// - /// 商品 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 租户 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 门店 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long StoreId { get; init; } - - /// - /// 分类 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long CategoryId { get; init; } - - /// - /// SPU 编码。 - /// - public string SpuCode { get; init; } = string.Empty; - - /// - /// 名称。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 副标题。 - /// - public string? Subtitle { get; init; } - - /// - /// 单位。 - /// - public string? Unit { get; init; } - - /// - /// 现价。 - /// - public decimal Price { get; init; } - - /// - /// 原价。 - /// - public decimal? OriginalPrice { get; init; } - - /// - /// 库存数量。 - /// - public int? StockQuantity { get; init; } - - /// - /// 每单限购。 - /// - public int? MaxQuantityPerOrder { get; init; } - - /// - /// 状态。 - /// - public ProductStatus Status { get; init; } - - /// - /// 主图。 - /// - public string? CoverImage { get; init; } - - /// - /// 图集。 - /// - public string? GalleryImages { get; init; } - - /// - /// 描述。 - /// - public string? Description { get; init; } - - /// - /// 支持堂食。 - /// - public bool EnableDineIn { get; init; } - - /// - /// 支持自提。 - /// - public bool EnablePickup { get; init; } - - /// - /// 支持配送。 - /// - public bool EnableDelivery { get; init; } - - /// - /// 是否推荐。 - /// - public bool IsFeatured { get; init; } - - /// - /// 创建时间。 - /// - public DateTime CreatedAt { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductMediaAssetDto.cs b/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductMediaAssetDto.cs deleted file mode 100644 index d4a3279..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductMediaAssetDto.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Products.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Products.Dto; - -/// -/// 商品媒资 DTO。 -/// -public sealed record ProductMediaAssetDto -{ - /// - /// 媒资 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 商品 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long ProductId { get; init; } - - /// - /// 类型。 - /// - public MediaAssetType MediaType { get; init; } - - /// - /// URL。 - /// - public string Url { get; init; } = string.Empty; - - /// - /// 文案。 - /// - public string? Caption { get; init; } - - /// - /// 排序。 - /// - public int SortOrder { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductPricingRuleDto.cs b/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductPricingRuleDto.cs deleted file mode 100644 index 04961fb..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductPricingRuleDto.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Products.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Products.Dto; - -/// -/// 价格策略 DTO。 -/// -public sealed record ProductPricingRuleDto -{ - /// - /// 策略 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 商品 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long ProductId { get; init; } - - /// - /// 策略类型。 - /// - public PricingRuleType RuleType { get; init; } - - /// - /// 价格。 - /// - public decimal Price { get; init; } - - /// - /// 条件 JSON。 - /// - public string ConditionsJson { get; init; } = string.Empty; - - /// - /// 星期规则。 - /// - public string? WeekdaysJson { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductSkuDto.cs b/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductSkuDto.cs deleted file mode 100644 index 4b76869..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Dto/ProductSkuDto.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Products.Dto; - -/// -/// SKU DTO。 -/// -public sealed record ProductSkuDto -{ - /// - /// SKU ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 商品 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long ProductId { get; init; } - - /// - /// 编码。 - /// - public string SkuCode { get; init; } = string.Empty; - - /// - /// 条形码。 - /// - public string? Barcode { get; init; } - - /// - /// 售价。 - /// - public decimal Price { get; init; } - - /// - /// 原价。 - /// - public decimal? OriginalPrice { get; init; } - - /// - /// 库存。 - /// - public int? StockQuantity { get; init; } - - /// - /// 重量。 - /// - public decimal? Weight { get; init; } - - /// - /// 规格属性 JSON。 - /// - public string AttributesJson { get; init; } = string.Empty; - - /// - /// 排序。 - /// - public int SortOrder { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Dto/StoreMenuDto.cs b/src/Application/TakeoutSaaS.Application/App/Products/Dto/StoreMenuDto.cs deleted file mode 100644 index 5429d43..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Dto/StoreMenuDto.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text.Json.Serialization; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Products.Dto; - -/// -/// 门店菜单数据传输对象。 -/// -public sealed record StoreMenuDto -{ - /// - /// 门店 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long StoreId { get; init; } - - /// - /// 分类与商品集合。 - /// - public IReadOnlyList Categories { get; init; } = []; - - /// - /// 菜单生成时间(UTC)。 - /// - public DateTime GeneratedAt { get; init; } - - /// - /// 客户端请求的增量时间(UTC)。 - /// - public DateTime? UpdatedAfter { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Handlers/CreateProductCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Products/Handlers/CreateProductCommandHandler.cs deleted file mode 100644 index 2bf1e33..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Handlers/CreateProductCommandHandler.cs +++ /dev/null @@ -1,78 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Products.Commands; -using TakeoutSaaS.Application.App.Products.Dto; -using TakeoutSaaS.Domain.Products.Entities; -using TakeoutSaaS.Domain.Products.Repositories; - -namespace TakeoutSaaS.Application.App.Products.Handlers; - -/// -/// 创建商品命令处理器。 -/// -public sealed class CreateProductCommandHandler(IProductRepository productRepository, ILogger logger) - : IRequestHandler -{ - private readonly IProductRepository _productRepository = productRepository; - private readonly ILogger _logger = logger; - - /// - public async Task Handle(CreateProductCommand request, CancellationToken cancellationToken) - { - // 1. 构建实体 - var product = new Product - { - StoreId = request.StoreId, - CategoryId = request.CategoryId, - SpuCode = request.SpuCode.Trim(), - Name = request.Name.Trim(), - Subtitle = request.Subtitle?.Trim(), - Unit = request.Unit?.Trim(), - Price = request.Price, - OriginalPrice = request.OriginalPrice, - StockQuantity = request.StockQuantity, - MaxQuantityPerOrder = request.MaxQuantityPerOrder, - Status = request.Status, - CoverImage = request.CoverImage?.Trim(), - GalleryImages = request.GalleryImages?.Trim(), - Description = request.Description?.Trim(), - EnableDineIn = request.EnableDineIn, - EnablePickup = request.EnablePickup, - EnableDelivery = request.EnableDelivery, - IsFeatured = request.IsFeatured - }; - - // 2. 持久化 - await _productRepository.AddProductAsync(product, cancellationToken); - await _productRepository.SaveChangesAsync(cancellationToken); - _logger.LogInformation("创建商品 {ProductId} - {ProductName}", product.Id, product.Name); - - // 3. 返回 DTO - return MapToDto(product); - } - - private static ProductDto MapToDto(Product product) => new() - { - Id = product.Id, - TenantId = product.TenantId, - StoreId = product.StoreId, - CategoryId = product.CategoryId, - SpuCode = product.SpuCode, - Name = product.Name, - Subtitle = product.Subtitle, - Unit = product.Unit, - Price = product.Price, - OriginalPrice = product.OriginalPrice, - StockQuantity = product.StockQuantity, - MaxQuantityPerOrder = product.MaxQuantityPerOrder, - Status = product.Status, - CoverImage = product.CoverImage, - GalleryImages = product.GalleryImages, - Description = product.Description, - EnableDineIn = product.EnableDineIn, - EnablePickup = product.EnablePickup, - EnableDelivery = product.EnableDelivery, - IsFeatured = product.IsFeatured, - CreatedAt = product.CreatedAt - }; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Handlers/DeleteProductCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Products/Handlers/DeleteProductCommandHandler.cs deleted file mode 100644 index f06cfa1..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Handlers/DeleteProductCommandHandler.cs +++ /dev/null @@ -1,40 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Products.Commands; -using TakeoutSaaS.Domain.Products.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Products.Handlers; - -/// -/// 删除商品命令处理器。 -/// -public sealed class DeleteProductCommandHandler( - IProductRepository productRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - private readonly IProductRepository _productRepository = productRepository; - private readonly ITenantProvider _tenantProvider = tenantProvider; - private readonly ILogger _logger = logger; - - /// - public async Task Handle(DeleteProductCommand request, CancellationToken cancellationToken) - { - // 1. 校验存在性 - var tenantId = _tenantProvider.GetCurrentTenantId(); - var existing = await _productRepository.FindByIdAsync(request.ProductId, tenantId, cancellationToken); - if (existing == null) - { - return false; - } - - // 2. 删除 - await _productRepository.DeleteProductAsync(request.ProductId, tenantId, cancellationToken); - await _productRepository.SaveChangesAsync(cancellationToken); - _logger.LogInformation("删除商品 {ProductId}", request.ProductId); - - return true; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Handlers/GetProductByIdQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Products/Handlers/GetProductByIdQueryHandler.cs deleted file mode 100644 index bed5199..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Handlers/GetProductByIdQueryHandler.cs +++ /dev/null @@ -1,28 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Products.Dto; -using TakeoutSaaS.Application.App.Products.Queries; -using TakeoutSaaS.Domain.Products.Entities; -using TakeoutSaaS.Domain.Products.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Products.Handlers; - -/// -/// 商品详情查询处理器。 -/// -public sealed class GetProductByIdQueryHandler( - IProductRepository productRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - private readonly IProductRepository _productRepository = productRepository; - private readonly ITenantProvider _tenantProvider = tenantProvider; - - /// - public async Task Handle(GetProductByIdQuery request, CancellationToken cancellationToken) - { - var tenantId = _tenantProvider.GetCurrentTenantId(); - var product = await _productRepository.FindByIdAsync(request.ProductId, tenantId, cancellationToken); - return product == null ? null : ProductMapping.ToDto(product); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Handlers/GetProductDetailQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Products/Handlers/GetProductDetailQueryHandler.cs deleted file mode 100644 index 828f1c8..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Handlers/GetProductDetailQueryHandler.cs +++ /dev/null @@ -1,63 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Products.Dto; -using TakeoutSaaS.Application.App.Products.Queries; -using TakeoutSaaS.Domain.Products.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Products.Handlers; - -/// -/// 商品全量详情查询处理器。 -/// -public sealed class GetProductDetailQueryHandler( - IProductRepository productRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - public async Task Handle(GetProductDetailQuery request, CancellationToken cancellationToken) - { - // 1. 读取 SPU - var tenantId = tenantProvider.GetCurrentTenantId(); - var product = await productRepository.FindByIdAsync(request.ProductId, tenantId, cancellationToken); - if (product is null) - { - return null; - } - - // 2. 查询子项 - var skusTask = productRepository.GetSkusAsync(product.Id, tenantId, cancellationToken); - var attrGroupsTask = productRepository.GetAttributeGroupsAsync(product.Id, tenantId, cancellationToken); - var attrOptionsTask = productRepository.GetAttributeOptionsAsync(product.Id, tenantId, cancellationToken); - var addonGroupsTask = productRepository.GetAddonGroupsAsync(product.Id, tenantId, cancellationToken); - var addonOptionsTask = productRepository.GetAddonOptionsAsync(product.Id, tenantId, cancellationToken); - var mediaTask = productRepository.GetMediaAssetsAsync(product.Id, tenantId, cancellationToken); - var pricingTask = productRepository.GetPricingRulesAsync(product.Id, tenantId, cancellationToken); - - await Task.WhenAll(skusTask, attrGroupsTask, attrOptionsTask, addonGroupsTask, addonOptionsTask, mediaTask, pricingTask); - - // 3. 组装 DTO - var skus = await skusTask; - var attrGroups = await attrGroupsTask; - var attrOptions = (await attrOptionsTask).ToLookup(x => x.AttributeGroupId); - var addonGroups = await addonGroupsTask; - var addonOptions = (await addonOptionsTask).ToLookup(x => x.AddonGroupId); - var mediaAssets = await mediaTask; - var pricingRules = await pricingTask; - var detail = new ProductDetailDto - { - Product = ProductMapping.ToDto(product), - Skus = skus.Select(ProductMapping.ToDto).ToList(), - AttributeGroups = attrGroups - .Select(g => ProductMapping.ToDto(g, attrOptions[g.Id].ToList())) - .ToList(), - AddonGroups = addonGroups - .Select(g => ProductMapping.ToDto(g, addonOptions[g.Id].ToList())) - .ToList(), - MediaAssets = mediaAssets.Select(ProductMapping.ToDto).ToList(), - PricingRules = pricingRules.Select(ProductMapping.ToDto).ToList() - }; - - return detail; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Handlers/GetStoreMenuQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Products/Handlers/GetStoreMenuQueryHandler.cs deleted file mode 100644 index bde1465..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Handlers/GetStoreMenuQueryHandler.cs +++ /dev/null @@ -1,136 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Products.Dto; -using TakeoutSaaS.Application.App.Products.Queries; -using TakeoutSaaS.Domain.Products.Entities; -using TakeoutSaaS.Domain.Products.Enums; -using TakeoutSaaS.Domain.Products.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Products.Handlers; - -/// -/// 门店菜单查询处理器。 -/// -public sealed class GetStoreMenuQueryHandler( - IProductRepository productRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(GetStoreMenuQuery request, CancellationToken cancellationToken) - { - // 1. 准备上下文 - var tenantId = tenantProvider.GetCurrentTenantId(); - var updatedAfterUtc = request.UpdatedAfter?.ToUniversalTime(); - // 2. 获取分类 - var categories = await productRepository.GetCategoriesByStoreAsync(tenantId, request.StoreId, true, cancellationToken); - // 3. 读取上架商品(支持增量) - var products = await productRepository.SearchAsync(tenantId, request.StoreId, null, ProductStatus.OnSale, cancellationToken, updatedAfterUtc); - if (products.Count == 0) - { - logger.LogInformation("门店 {StoreId} 没有上架商品,返回空菜单", request.StoreId); - return new StoreMenuDto - { - StoreId = request.StoreId, - GeneratedAt = DateTime.UtcNow, - UpdatedAfter = updatedAfterUtc, - Categories = categories - .OrderBy(x => x.SortOrder) - .Select(category => new ProductCategoryMenuDto - { - Id = category.Id, - StoreId = category.StoreId, - Name = category.Name, - Description = category.Description, - SortOrder = category.SortOrder, - IsEnabled = category.IsEnabled, - Products = [] - }) - .ToList() - }; - } - - // 4. 并发加载子表数据 - var productIds = products.Select(x => x.Id).ToList(); - var skusTask = productRepository.GetSkusByProductIdsAsync(productIds, tenantId, cancellationToken); - var attributeGroupsTask = productRepository.GetAttributeGroupsByProductIdsAsync(productIds, tenantId, cancellationToken); - var addonGroupsTask = productRepository.GetAddonGroupsByProductIdsAsync(productIds, tenantId, cancellationToken); - var mediaTask = productRepository.GetMediaAssetsByProductIdsAsync(productIds, tenantId, cancellationToken); - var pricingTask = productRepository.GetPricingRulesByProductIdsAsync(productIds, tenantId, cancellationToken); - await Task.WhenAll(skusTask, attributeGroupsTask, addonGroupsTask, mediaTask, pricingTask); - var attributeGroups = await attributeGroupsTask; - var addonGroups = await addonGroupsTask; - // 批量读取规格与加料选项 - var attributeOptionsTask = attributeGroups.Count == 0 - ? Task.FromResult>(Array.Empty()) - : productRepository.GetAttributeOptionsByGroupIdsAsync(attributeGroups.Select(x => x.Id).ToList(), tenantId, cancellationToken); - var addonOptionsTask = addonGroups.Count == 0 - ? Task.FromResult>(Array.Empty()) - : productRepository.GetAddonOptionsByGroupIdsAsync(addonGroups.Select(x => x.Id).ToList(), tenantId, cancellationToken); - await Task.WhenAll(attributeOptionsTask, addonOptionsTask); - - // 5. 建立查找表 - var skuLookup = (await skusTask).ToLookup(x => x.ProductId); - var attrGroupLookup = attributeGroups.ToLookup(x => x.ProductId); - var attrOptionLookup = (await attributeOptionsTask).ToLookup(x => x.AttributeGroupId); - var addonGroupLookup = addonGroups.ToLookup(x => x.ProductId); - var addonOptionLookup = (await addonOptionsTask).ToLookup(x => x.AddonGroupId); - var mediaLookup = (await mediaTask).ToLookup(x => x.ProductId); - var pricingLookup = (await pricingTask).ToLookup(x => x.ProductId); - // 6. 组装商品详情 - var productDetails = products.ToDictionary( - product => product.Id, - product => - { - var attributeDtos = attrGroupLookup[product.Id] - .Select(group => ProductMapping.ToDto(group, attrOptionLookup[group.Id].ToList())) - .ToList(); - var addonDtos = addonGroupLookup[product.Id] - .Select(group => ProductMapping.ToDto(group, addonOptionLookup[group.Id].ToList())) - .ToList(); - return new ProductDetailDto - { - Product = ProductMapping.ToDto(product), - Skus = skuLookup[product.Id].Select(ProductMapping.ToDto).ToList(), - AttributeGroups = attributeDtos, - AddonGroups = addonDtos, - MediaAssets = mediaLookup[product.Id].Select(ProductMapping.ToDto).ToList(), - PricingRules = pricingLookup[product.Id].Select(ProductMapping.ToDto).ToList() - }; - }); - // 7. 组装分类菜单 - var productsByCategory = products.ToLookup(x => x.CategoryId); - var categoryMenu = categories - .OrderBy(x => x.SortOrder) - .Select(category => - { - var categoryProducts = productsByCategory[category.Id] - .Select(p => productDetails[p.Id]) - .ToList(); - return new ProductCategoryMenuDto - { - Id = category.Id, - StoreId = category.StoreId, - Name = category.Name, - Description = category.Description, - SortOrder = category.SortOrder, - IsEnabled = category.IsEnabled, - Products = categoryProducts - }; - }) - .ToList(); - return new StoreMenuDto - { - StoreId = request.StoreId, - GeneratedAt = DateTime.UtcNow, - UpdatedAfter = updatedAfterUtc, - Categories = categoryMenu - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Handlers/PublishProductCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Products/Handlers/PublishProductCommandHandler.cs deleted file mode 100644 index fd71ada..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Handlers/PublishProductCommandHandler.cs +++ /dev/null @@ -1,49 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Products.Commands; -using TakeoutSaaS.Application.App.Products.Dto; -using TakeoutSaaS.Application.App.Products.Queries; -using TakeoutSaaS.Domain.Products.Enums; -using TakeoutSaaS.Domain.Products.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Products.Handlers; - -/// -/// 商品上架处理器。 -/// -public sealed class PublishProductCommandHandler( - IProductRepository productRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(PublishProductCommand request, CancellationToken cancellationToken) - { - // 1. 读取商品 - var tenantId = tenantProvider.GetCurrentTenantId(); - var product = await productRepository.FindByIdAsync(request.ProductId, tenantId, cancellationToken); - if (product is null) - { - return null; - } - - // 2. 校验 SKU 可售 - var skus = await productRepository.GetSkusAsync(product.Id, tenantId, cancellationToken); - if (skus.Count == 0) - { - throw new BusinessException(ErrorCodes.Conflict, "请先配置可售 SKU 后再上架"); - } - - // 3. 上架 - product.Status = ProductStatus.OnSale; - await productRepository.UpdateProductAsync(product, cancellationToken); - await productRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("商品上架 {ProductId}", product.Id); - - return ProductMapping.ToDto(product); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Handlers/ReplaceProductAddonsCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Products/Handlers/ReplaceProductAddonsCommandHandler.cs deleted file mode 100644 index af61144..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Handlers/ReplaceProductAddonsCommandHandler.cs +++ /dev/null @@ -1,74 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Products.Commands; -using TakeoutSaaS.Application.App.Products.Dto; -using TakeoutSaaS.Domain.Products.Entities; -using TakeoutSaaS.Domain.Products.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Products.Handlers; - -/// -/// 替换加料处理器。 -/// -public sealed class ReplaceProductAddonsCommandHandler( - IProductRepository productRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler> -{ - /// - public async Task> Handle(ReplaceProductAddonsCommand request, CancellationToken cancellationToken) - { - // 1. 校验商品 - var tenantId = tenantProvider.GetCurrentTenantId(); - var product = await productRepository.FindByIdAsync(request.ProductId, tenantId, cancellationToken); - if (product is null) - { - throw new BusinessException(ErrorCodes.NotFound, "商品不存在"); - } - - // 2. 校验组名唯一 - var names = request.AddonGroups.Select(x => x.Name.Trim()).ToList(); - if (names.Count != names.Distinct(StringComparer.OrdinalIgnoreCase).Count()) - { - throw new BusinessException(ErrorCodes.Conflict, "加料组名称重复"); - } - - // 3. 替换 - await productRepository.RemoveAddonGroupsAsync(request.ProductId, tenantId, cancellationToken); - // 重新插入组 - var groupEntities = request.AddonGroups.Select(g => new ProductAddonGroup - { - ProductId = request.ProductId, - Name = g.Name.Trim(), - MinSelect = g.MinSelect, - MaxSelect = g.MaxSelect, - SortOrder = g.SortOrder - }).ToList(); - await productRepository.AddAddonGroupsAsync(groupEntities, [], cancellationToken); - await productRepository.SaveChangesAsync(cancellationToken); - // 重新建立组与请求的映射 - var groupIdLookup = groupEntities.Zip(request.AddonGroups, (entity, dto) => (entity, dto)) - .ToDictionary(x => x.dto, x => x.entity.Id); - // 构建选项实体 - var optionEntities = request.AddonGroups - .SelectMany(dto => dto.Options.Select(o => new ProductAddonOption - { - AddonGroupId = groupIdLookup[dto], - Name = o.Name.Trim(), - ExtraPrice = o.ExtraPrice, - SortOrder = o.SortOrder - })) - .ToList(); - await productRepository.AddAddonGroupsAsync([], optionEntities, cancellationToken); - await productRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("替换商品 {ProductId} 加料组 {Count} 个", request.ProductId, groupEntities.Count); - - return groupEntities - .Select(g => ProductMapping.ToDto(g, optionEntities.Where(o => o.AddonGroupId == g.Id).ToList())) - .ToList(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Handlers/ReplaceProductAttributesCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Products/Handlers/ReplaceProductAttributesCommandHandler.cs deleted file mode 100644 index 9cef4d1..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Handlers/ReplaceProductAttributesCommandHandler.cs +++ /dev/null @@ -1,77 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Products.Commands; -using TakeoutSaaS.Application.App.Products.Dto; -using TakeoutSaaS.Domain.Products.Entities; -using TakeoutSaaS.Domain.Products.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Products.Handlers; - -/// -/// 替换规格处理器。 -/// -public sealed class ReplaceProductAttributesCommandHandler( - IProductRepository productRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler> -{ - /// - public async Task> Handle(ReplaceProductAttributesCommand request, CancellationToken cancellationToken) - { - // 1. 校验商品 - var tenantId = tenantProvider.GetCurrentTenantId(); - var product = await productRepository.FindByIdAsync(request.ProductId, tenantId, cancellationToken); - if (product is null) - { - throw new BusinessException(ErrorCodes.NotFound, "商品不存在"); - } - - // 2. 组名唯一 - var groupNames = request.AttributeGroups.Select(x => x.Name.Trim()).ToList(); - if (groupNames.Count != groupNames.Distinct(StringComparer.OrdinalIgnoreCase).Count()) - { - throw new BusinessException(ErrorCodes.Conflict, "规格组名称重复"); - } - - // 3. 替换 - await productRepository.RemoveAttributeGroupsAsync(request.ProductId, tenantId, cancellationToken); - - var groupEntities = request.AttributeGroups.Select(g => new ProductAttributeGroup - { - ProductId = request.ProductId, - Name = g.Name.Trim(), - SelectionType = (Domain.Products.Enums.AttributeSelectionType)g.SelectionType, - SortOrder = g.SortOrder - }).ToList(); - - // 4. 持久化(分批保障 FK 正确) - await productRepository.AddAttributeGroupsAsync(groupEntities, [], cancellationToken); - await productRepository.SaveChangesAsync(cancellationToken); - - // 重新建立选项的 GroupId 映射 - var groupIdLookup = groupEntities.Zip(request.AttributeGroups, (entity, dto) => (entity, dto)) - .ToDictionary(x => x.dto, x => x.entity.Id); - - var optionEntities = request.AttributeGroups - .SelectMany(dto => dto.Options.Select(o => new ProductAttributeOption - { - AttributeGroupId = groupIdLookup[dto], - Name = o.Name.Trim(), - SortOrder = o.SortOrder - })) - .ToList(); - - await productRepository.AddAttributeGroupsAsync([], optionEntities, cancellationToken); - await productRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("替换商品 {ProductId} 规格组 {GroupCount} 个", request.ProductId, groupEntities.Count); - - // 5. 返回 DTO - return groupEntities - .Select(g => ProductMapping.ToDto(g, optionEntities.Where(o => o.AttributeGroupId == g.Id).ToList())) - .ToList(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Handlers/ReplaceProductMediaCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Products/Handlers/ReplaceProductMediaCommandHandler.cs deleted file mode 100644 index 4c704f4..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Handlers/ReplaceProductMediaCommandHandler.cs +++ /dev/null @@ -1,51 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Products.Commands; -using TakeoutSaaS.Application.App.Products.Dto; -using TakeoutSaaS.Domain.Products.Entities; -using TakeoutSaaS.Domain.Products.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Products.Handlers; - -/// -/// 替换媒资处理器。 -/// -public sealed class ReplaceProductMediaCommandHandler( - IProductRepository productRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler> -{ - /// - public async Task> Handle(ReplaceProductMediaCommand request, CancellationToken cancellationToken) - { - // 1. 校验商品 - var tenantId = tenantProvider.GetCurrentTenantId(); - var product = await productRepository.FindByIdAsync(request.ProductId, tenantId, cancellationToken); - if (product is null) - { - throw new BusinessException(ErrorCodes.NotFound, "商品不存在"); - } - - // 2. 替换 - await productRepository.RemoveMediaAssetsAsync(request.ProductId, tenantId, cancellationToken); - - var assets = request.MediaAssets.Select(a => new ProductMediaAsset - { - ProductId = request.ProductId, - MediaType = a.MediaType, - Url = a.Url.Trim(), - Caption = a.Caption?.Trim(), - SortOrder = a.SortOrder - }).ToList(); - - await productRepository.AddMediaAssetsAsync(assets, cancellationToken); - await productRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("替换商品 {ProductId} 媒资 {Count} 条", request.ProductId, assets.Count); - - return assets.Select(ProductMapping.ToDto).ToList(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Handlers/ReplaceProductPricingRulesCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Products/Handlers/ReplaceProductPricingRulesCommandHandler.cs deleted file mode 100644 index 8c02739..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Handlers/ReplaceProductPricingRulesCommandHandler.cs +++ /dev/null @@ -1,52 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Products.Commands; -using TakeoutSaaS.Application.App.Products.Dto; -using TakeoutSaaS.Domain.Products.Entities; -using TakeoutSaaS.Domain.Products.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Products.Handlers; - -/// -/// 替换价格策略处理器。 -/// -public sealed class ReplaceProductPricingRulesCommandHandler( - IProductRepository productRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler> -{ - /// - public async Task> Handle(ReplaceProductPricingRulesCommand request, CancellationToken cancellationToken) - { - // 1. 校验商品 - var tenantId = tenantProvider.GetCurrentTenantId(); - var product = await productRepository.FindByIdAsync(request.ProductId, tenantId, cancellationToken); - if (product is null) - { - throw new BusinessException(ErrorCodes.NotFound, "商品不存在"); - } - - // 2. 替换 - await productRepository.RemovePricingRulesAsync(request.ProductId, tenantId, cancellationToken); - - var rules = request.PricingRules.Select(r => new ProductPricingRule - { - ProductId = request.ProductId, - RuleType = r.RuleType, - ConditionsJson = r.ConditionsJson.Trim(), - Price = r.Price, - WeekdaysJson = r.WeekdaysJson, - SortOrder = 0 - }).ToList(); - - await productRepository.AddPricingRulesAsync(rules, cancellationToken); - await productRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("替换商品 {ProductId} 价格策略 {Count} 条", request.ProductId, rules.Count); - - return rules.Select(ProductMapping.ToDto).ToList(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Handlers/ReplaceProductSkusCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Products/Handlers/ReplaceProductSkusCommandHandler.cs deleted file mode 100644 index 9f62d45..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Handlers/ReplaceProductSkusCommandHandler.cs +++ /dev/null @@ -1,61 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Products.Commands; -using TakeoutSaaS.Application.App.Products.Dto; -using TakeoutSaaS.Domain.Products.Entities; -using TakeoutSaaS.Domain.Products.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Products.Handlers; - -/// -/// 替换 SKU 处理器。 -/// -public sealed class ReplaceProductSkusCommandHandler( - IProductRepository productRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler> -{ - /// - public async Task> Handle(ReplaceProductSkusCommand request, CancellationToken cancellationToken) - { - // 1. 校验商品存在 - var tenantId = tenantProvider.GetCurrentTenantId(); - var product = await productRepository.FindByIdAsync(request.ProductId, tenantId, cancellationToken); - if (product is null) - { - throw new BusinessException(ErrorCodes.NotFound, "商品不存在"); - } - - // 2. 校验 SKU 唯一性 - var codes = request.Skus.Select(x => x.SkuCode.Trim()).ToList(); - if (codes.Count != codes.Distinct(StringComparer.OrdinalIgnoreCase).Count()) - { - throw new BusinessException(ErrorCodes.Conflict, "SKU 编码重复"); - } - - // 3. 替换 - await productRepository.RemoveSkusAsync(request.ProductId, tenantId, cancellationToken); - var entities = request.Skus.Select(x => new ProductSku - { - ProductId = request.ProductId, - SkuCode = x.SkuCode.Trim(), - Barcode = x.Barcode?.Trim(), - Price = x.Price, - OriginalPrice = x.OriginalPrice, - StockQuantity = x.StockQuantity, - Weight = x.Weight, - AttributesJson = x.AttributesJson ?? string.Empty, - SortOrder = x.SortOrder - }).ToList(); - - await productRepository.AddSkusAsync(entities, cancellationToken); - await productRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("替换商品 {ProductId} 的 SKU 数量 {Count}", request.ProductId, entities.Count); - - return entities.Select(ProductMapping.ToDto).ToList(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Handlers/SearchProductsQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Products/Handlers/SearchProductsQueryHandler.cs deleted file mode 100644 index 660a35b..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Handlers/SearchProductsQueryHandler.cs +++ /dev/null @@ -1,75 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Products.Dto; -using TakeoutSaaS.Application.App.Products.Queries; -using TakeoutSaaS.Domain.Products.Repositories; -using TakeoutSaaS.Shared.Abstractions.Results; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Products.Handlers; - -/// -/// 商品列表查询处理器。 -/// -public sealed class SearchProductsQueryHandler( - IProductRepository productRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - private readonly IProductRepository _productRepository = productRepository; - private readonly ITenantProvider _tenantProvider = tenantProvider; - - /// - public async Task> Handle(SearchProductsQuery request, CancellationToken cancellationToken) - { - var tenantId = _tenantProvider.GetCurrentTenantId(); - var products = await _productRepository.SearchAsync(tenantId, request.StoreId, request.CategoryId, request.Status, cancellationToken); - - var sorted = ApplySorting(products, request.SortBy, request.SortDescending); - var paged = sorted - .Skip((request.Page - 1) * request.PageSize) - .Take(request.PageSize) - .ToList(); - - var items = paged.Select(MapToDto).ToList(); - return new PagedResult(items, request.Page, request.PageSize, products.Count); - } - - private static IOrderedEnumerable ApplySorting( - IReadOnlyCollection products, - string? sortBy, - bool sortDescending) - { - return sortBy?.ToLowerInvariant() switch - { - "name" => sortDescending ? products.OrderByDescending(x => x.Name) : products.OrderBy(x => x.Name), - "price" => sortDescending ? products.OrderByDescending(x => x.Price) : products.OrderBy(x => x.Price), - "status" => sortDescending ? products.OrderByDescending(x => x.Status) : products.OrderBy(x => x.Status), - _ => sortDescending ? products.OrderByDescending(x => x.CreatedAt) : products.OrderBy(x => x.CreatedAt) - }; - } - - private static ProductDto MapToDto(Domain.Products.Entities.Product product) => new() - { - Id = product.Id, - TenantId = product.TenantId, - StoreId = product.StoreId, - CategoryId = product.CategoryId, - SpuCode = product.SpuCode, - Name = product.Name, - Subtitle = product.Subtitle, - Unit = product.Unit, - Price = product.Price, - OriginalPrice = product.OriginalPrice, - StockQuantity = product.StockQuantity, - MaxQuantityPerOrder = product.MaxQuantityPerOrder, - Status = product.Status, - CoverImage = product.CoverImage, - GalleryImages = product.GalleryImages, - Description = product.Description, - EnableDineIn = product.EnableDineIn, - EnablePickup = product.EnablePickup, - EnableDelivery = product.EnableDelivery, - IsFeatured = product.IsFeatured, - CreatedAt = product.CreatedAt - }; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Handlers/UnpublishProductCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Products/Handlers/UnpublishProductCommandHandler.cs deleted file mode 100644 index 83fe4c8..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Handlers/UnpublishProductCommandHandler.cs +++ /dev/null @@ -1,39 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Products.Commands; -using TakeoutSaaS.Application.App.Products.Dto; -using TakeoutSaaS.Domain.Products.Enums; -using TakeoutSaaS.Domain.Products.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Products.Handlers; - -/// -/// 商品下架处理器。 -/// -public sealed class UnpublishProductCommandHandler( - IProductRepository productRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(UnpublishProductCommand request, CancellationToken cancellationToken) - { - // 1. 读取商品 - var tenantId = tenantProvider.GetCurrentTenantId(); - var product = await productRepository.FindByIdAsync(request.ProductId, tenantId, cancellationToken); - if (product is null) - { - return null; - } - - // 2. 下架 - product.Status = ProductStatus.OffShelf; - await productRepository.UpdateProductAsync(product, cancellationToken); - await productRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("商品下架 {ProductId}", product.Id); - - return ProductMapping.ToDto(product); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Handlers/UpdateProductCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Products/Handlers/UpdateProductCommandHandler.cs deleted file mode 100644 index e616788..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Handlers/UpdateProductCommandHandler.cs +++ /dev/null @@ -1,88 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Products.Commands; -using TakeoutSaaS.Application.App.Products.Dto; -using TakeoutSaaS.Domain.Products.Entities; -using TakeoutSaaS.Domain.Products.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Products.Handlers; - -/// -/// 更新商品命令处理器。 -/// -public sealed class UpdateProductCommandHandler( - IProductRepository productRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - private readonly IProductRepository _productRepository = productRepository; - private readonly ITenantProvider _tenantProvider = tenantProvider; - private readonly ILogger _logger = logger; - - /// - public async Task Handle(UpdateProductCommand request, CancellationToken cancellationToken) - { - // 1. 读取商品 - var tenantId = _tenantProvider.GetCurrentTenantId(); - var existing = await _productRepository.FindByIdAsync(request.ProductId, tenantId, cancellationToken); - if (existing == null) - { - return null; - } - - // 2. 更新字段 - existing.StoreId = request.StoreId; - existing.CategoryId = request.CategoryId; - existing.SpuCode = request.SpuCode.Trim(); - existing.Name = request.Name.Trim(); - existing.Subtitle = request.Subtitle?.Trim(); - existing.Unit = request.Unit?.Trim(); - existing.Price = request.Price; - existing.OriginalPrice = request.OriginalPrice; - existing.StockQuantity = request.StockQuantity; - existing.MaxQuantityPerOrder = request.MaxQuantityPerOrder; - existing.Status = request.Status; - existing.CoverImage = request.CoverImage?.Trim(); - existing.GalleryImages = request.GalleryImages?.Trim(); - existing.Description = request.Description?.Trim(); - existing.EnableDineIn = request.EnableDineIn; - existing.EnablePickup = request.EnablePickup; - existing.EnableDelivery = request.EnableDelivery; - existing.IsFeatured = request.IsFeatured; - - // 3. 持久化 - await _productRepository.UpdateProductAsync(existing, cancellationToken); - await _productRepository.SaveChangesAsync(cancellationToken); - _logger.LogInformation("更新商品 {ProductId} - {ProductName}", existing.Id, existing.Name); - - // 4. 返回 DTO - return MapToDto(existing); - } - - private static ProductDto MapToDto(Product product) => new() - { - Id = product.Id, - TenantId = product.TenantId, - StoreId = product.StoreId, - CategoryId = product.CategoryId, - SpuCode = product.SpuCode, - Name = product.Name, - Subtitle = product.Subtitle, - Unit = product.Unit, - Price = product.Price, - OriginalPrice = product.OriginalPrice, - StockQuantity = product.StockQuantity, - MaxQuantityPerOrder = product.MaxQuantityPerOrder, - Status = product.Status, - CoverImage = product.CoverImage, - GalleryImages = product.GalleryImages, - Description = product.Description, - EnableDineIn = product.EnableDineIn, - EnablePickup = product.EnablePickup, - EnableDelivery = product.EnableDelivery, - IsFeatured = product.IsFeatured, - CreatedAt = product.CreatedAt - }; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/ProductMapping.cs b/src/Application/TakeoutSaaS.Application/App/Products/ProductMapping.cs deleted file mode 100644 index 77cf89f..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/ProductMapping.cs +++ /dev/null @@ -1,133 +0,0 @@ -using TakeoutSaaS.Application.App.Products.Dto; -using TakeoutSaaS.Domain.Products.Entities; - -namespace TakeoutSaaS.Application.App.Products; - -/// -/// 商品映射辅助。 -/// -public static class ProductMapping -{ - /// - /// 映射 SPU DTO。 - /// - /// 商品实体。 - /// DTO。 - public static ProductDto ToDto(Product product) => new() - { - Id = product.Id, - TenantId = product.TenantId, - StoreId = product.StoreId, - CategoryId = product.CategoryId, - SpuCode = product.SpuCode, - Name = product.Name, - Subtitle = product.Subtitle, - Unit = product.Unit, - Price = product.Price, - OriginalPrice = product.OriginalPrice, - StockQuantity = product.StockQuantity, - MaxQuantityPerOrder = product.MaxQuantityPerOrder, - Status = product.Status, - CoverImage = product.CoverImage, - GalleryImages = product.GalleryImages, - Description = product.Description, - EnableDineIn = product.EnableDineIn, - EnablePickup = product.EnablePickup, - EnableDelivery = product.EnableDelivery, - IsFeatured = product.IsFeatured, - CreatedAt = product.CreatedAt - }; - - /// - /// 映射 SKU DTO。 - /// - public static ProductSkuDto ToDto(ProductSku sku) => new() - { - Id = sku.Id, - ProductId = sku.ProductId, - SkuCode = sku.SkuCode, - Barcode = sku.Barcode, - Price = sku.Price, - OriginalPrice = sku.OriginalPrice, - StockQuantity = sku.StockQuantity, - Weight = sku.Weight, - AttributesJson = sku.AttributesJson, - SortOrder = sku.SortOrder - }; - - /// - /// 映射规格组 DTO。 - /// - public static ProductAttributeGroupDto ToDto(ProductAttributeGroup group, IReadOnlyList options) => new() - { - Id = group.Id, - ProductId = group.ProductId, - Name = group.Name, - SelectionType = (int)group.SelectionType, - SortOrder = group.SortOrder, - Options = options.Select(ToDto).ToList() - }; - - /// - /// 映射规格选项 DTO。 - /// - public static ProductAttributeOptionDto ToDto(ProductAttributeOption option) => new() - { - Id = option.Id, - AttributeGroupId = option.AttributeGroupId, - Name = option.Name, - SortOrder = option.SortOrder - }; - - /// - /// 映射加料组 DTO。 - /// - public static ProductAddonGroupDto ToDto(ProductAddonGroup group, IReadOnlyList options) => new() - { - Id = group.Id, - ProductId = group.ProductId, - Name = group.Name, - MinSelect = group.MinSelect ?? 0, - MaxSelect = group.MaxSelect ?? 0, - SortOrder = group.SortOrder, - Options = options.Select(ToDto).ToList() - }; - - /// - /// 映射加料选项 DTO。 - /// - public static ProductAddonOptionDto ToDto(ProductAddonOption option) => new() - { - Id = option.Id, - AddonGroupId = option.AddonGroupId, - Name = option.Name, - ExtraPrice = option.ExtraPrice, - SortOrder = option.SortOrder - }; - - /// - /// 映射媒资 DTO。 - /// - public static ProductMediaAssetDto ToDto(ProductMediaAsset asset) => new() - { - Id = asset.Id, - ProductId = asset.ProductId, - MediaType = asset.MediaType, - Url = asset.Url, - Caption = asset.Caption, - SortOrder = asset.SortOrder - }; - - /// - /// 映射价格策略 DTO。 - /// - public static ProductPricingRuleDto ToDto(ProductPricingRule rule) => new() - { - Id = rule.Id, - ProductId = rule.ProductId, - RuleType = rule.RuleType, - Price = rule.Price, - ConditionsJson = rule.ConditionsJson, - WeekdaysJson = rule.WeekdaysJson - }; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Queries/GetProductByIdQuery.cs b/src/Application/TakeoutSaaS.Application/App/Products/Queries/GetProductByIdQuery.cs deleted file mode 100644 index 08830cb..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Queries/GetProductByIdQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Products.Dto; - -namespace TakeoutSaaS.Application.App.Products.Queries; - -/// -/// 获取商品详情查询。 -/// -public sealed class GetProductByIdQuery : IRequest -{ - /// - /// 商品 ID。 - /// - public long ProductId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Queries/GetProductDetailQuery.cs b/src/Application/TakeoutSaaS.Application/App/Products/Queries/GetProductDetailQuery.cs deleted file mode 100644 index a6e2c19..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Queries/GetProductDetailQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Products.Dto; - -namespace TakeoutSaaS.Application.App.Products.Queries; - -/// -/// 商品全量详情查询。 -/// -public sealed record GetProductDetailQuery : IRequest -{ - /// - /// 商品 ID。 - /// - public long ProductId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Queries/GetStoreMenuQuery.cs b/src/Application/TakeoutSaaS.Application/App/Products/Queries/GetStoreMenuQuery.cs deleted file mode 100644 index 472806b..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Queries/GetStoreMenuQuery.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using MediatR; -using TakeoutSaaS.Application.App.Products.Dto; - -namespace TakeoutSaaS.Application.App.Products.Queries; - -/// -/// 获取门店菜单查询。 -/// -public sealed record GetStoreMenuQuery : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 增量时间(UTC)。 - /// - public DateTime? UpdatedAfter { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Queries/SearchProductsQuery.cs b/src/Application/TakeoutSaaS.Application/App/Products/Queries/SearchProductsQuery.cs deleted file mode 100644 index b1d4b31..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Queries/SearchProductsQuery.cs +++ /dev/null @@ -1,47 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Products.Dto; -using TakeoutSaaS.Domain.Products.Enums; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.App.Products.Queries; - -/// -/// 商品列表查询。 -/// -public sealed class SearchProductsQuery : IRequest> -{ - /// - /// 门店 ID(可选)。 - /// - public long? StoreId { get; init; } - - /// - /// 分类 ID(可选)。 - /// - public long? CategoryId { get; init; } - - /// - /// 状态过滤。 - /// - public ProductStatus? Status { get; init; } - - /// - /// 页码。 - /// - public int Page { get; init; } = 1; - - /// - /// 每页条数。 - /// - public int PageSize { get; init; } = 20; - - /// - /// 排序字段(name/price/status/createdAt)。 - /// - public string? SortBy { get; init; } - - /// - /// 是否倒序。 - /// - public bool SortDescending { get; init; } = true; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Validators/CreateProductCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Products/Validators/CreateProductCommandValidator.cs deleted file mode 100644 index 91bd6ac..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Validators/CreateProductCommandValidator.cs +++ /dev/null @@ -1,29 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Products.Commands; - -namespace TakeoutSaaS.Application.App.Products.Validators; - -/// -/// 创建商品命令验证器。 -/// -public sealed class CreateProductCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public CreateProductCommandValidator() - { - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.CategoryId).GreaterThan(0); - RuleFor(x => x.SpuCode).NotEmpty().MaximumLength(32); - RuleFor(x => x.Name).NotEmpty().MaximumLength(128); - RuleFor(x => x.Subtitle).MaximumLength(256); - RuleFor(x => x.Unit).MaximumLength(16); - RuleFor(x => x.Price).GreaterThanOrEqualTo(0); - RuleFor(x => x.OriginalPrice).GreaterThanOrEqualTo(0).When(x => x.OriginalPrice.HasValue); - RuleFor(x => x.StockQuantity).GreaterThanOrEqualTo(0).When(x => x.StockQuantity.HasValue); - RuleFor(x => x.MaxQuantityPerOrder).GreaterThan(0).When(x => x.MaxQuantityPerOrder.HasValue); - RuleFor(x => x.CoverImage).MaximumLength(256); - RuleFor(x => x.GalleryImages).MaximumLength(1024); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Validators/PublishProductCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Products/Validators/PublishProductCommandValidator.cs deleted file mode 100644 index 4964237..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Validators/PublishProductCommandValidator.cs +++ /dev/null @@ -1,19 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Products.Commands; - -namespace TakeoutSaaS.Application.App.Products.Validators; - -/// -/// 上架商品命令验证器。 -/// -public sealed class PublishProductCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public PublishProductCommandValidator() - { - RuleFor(x => x.ProductId).GreaterThan(0); - RuleFor(x => x.Reason).MaximumLength(256); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Validators/ReplaceProductAddonsCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Products/Validators/ReplaceProductAddonsCommandValidator.cs deleted file mode 100644 index 37f52a8..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Validators/ReplaceProductAddonsCommandValidator.cs +++ /dev/null @@ -1,31 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Products.Commands; - -namespace TakeoutSaaS.Application.App.Products.Validators; - -/// -/// 替换加料验证器。 -/// -public sealed class ReplaceProductAddonsCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public ReplaceProductAddonsCommandValidator() - { - RuleFor(x => x.ProductId).GreaterThan(0); - RuleForEach(x => x.AddonGroups).ChildRules(group => - { - group.RuleFor(x => x.Name).NotEmpty().MaximumLength(64); - group.RuleFor(x => x.MinSelect).GreaterThanOrEqualTo(0); - group.RuleFor(x => x.MaxSelect).GreaterThanOrEqualTo(x => x.MinSelect); - group.RuleFor(x => x.SortOrder).GreaterThanOrEqualTo(0); - group.RuleForEach(x => x.Options).ChildRules(opt => - { - opt.RuleFor(x => x.Name).NotEmpty().MaximumLength(64); - opt.RuleFor(x => x.ExtraPrice).GreaterThanOrEqualTo(0).When(x => x.ExtraPrice.HasValue); - opt.RuleFor(x => x.SortOrder).GreaterThanOrEqualTo(0); - }); - }); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Validators/ReplaceProductAttributesCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Products/Validators/ReplaceProductAttributesCommandValidator.cs deleted file mode 100644 index 7cc5e10..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Validators/ReplaceProductAttributesCommandValidator.cs +++ /dev/null @@ -1,28 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Products.Commands; - -namespace TakeoutSaaS.Application.App.Products.Validators; - -/// -/// 替换规格验证器。 -/// -public sealed class ReplaceProductAttributesCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public ReplaceProductAttributesCommandValidator() - { - RuleFor(x => x.ProductId).GreaterThan(0); - RuleForEach(x => x.AttributeGroups).ChildRules(group => - { - group.RuleFor(x => x.Name).NotEmpty().MaximumLength(64); - group.RuleFor(x => x.SortOrder).GreaterThanOrEqualTo(0); - group.RuleForEach(x => x.Options).ChildRules(opt => - { - opt.RuleFor(x => x.Name).NotEmpty().MaximumLength(64); - opt.RuleFor(x => x.SortOrder).GreaterThanOrEqualTo(0); - }); - }); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Validators/ReplaceProductMediaCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Products/Validators/ReplaceProductMediaCommandValidator.cs deleted file mode 100644 index fa27cb7..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Validators/ReplaceProductMediaCommandValidator.cs +++ /dev/null @@ -1,24 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Products.Commands; - -namespace TakeoutSaaS.Application.App.Products.Validators; - -/// -/// 替换媒资验证器。 -/// -public sealed class ReplaceProductMediaCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public ReplaceProductMediaCommandValidator() - { - RuleFor(x => x.ProductId).GreaterThan(0); - RuleForEach(x => x.MediaAssets).ChildRules(asset => - { - asset.RuleFor(x => x.Url).NotEmpty().MaximumLength(512); - asset.RuleFor(x => x.Caption).MaximumLength(256); - asset.RuleFor(x => x.SortOrder).GreaterThanOrEqualTo(0); - }); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Validators/ReplaceProductPricingRulesCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Products/Validators/ReplaceProductPricingRulesCommandValidator.cs deleted file mode 100644 index 5cdac59..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Validators/ReplaceProductPricingRulesCommandValidator.cs +++ /dev/null @@ -1,23 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Products.Commands; - -namespace TakeoutSaaS.Application.App.Products.Validators; - -/// -/// 替换价格策略验证器。 -/// -public sealed class ReplaceProductPricingRulesCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public ReplaceProductPricingRulesCommandValidator() - { - RuleFor(x => x.ProductId).GreaterThan(0); - RuleForEach(x => x.PricingRules).ChildRules(rule => - { - rule.RuleFor(x => x.Price).GreaterThan(0); - rule.RuleFor(x => x.ConditionsJson).NotEmpty(); - }); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Validators/ReplaceProductSkusCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Products/Validators/ReplaceProductSkusCommandValidator.cs deleted file mode 100644 index 7e4a387..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Validators/ReplaceProductSkusCommandValidator.cs +++ /dev/null @@ -1,26 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Products.Commands; - -namespace TakeoutSaaS.Application.App.Products.Validators; - -/// -/// 替换 SKU 验证器。 -/// -public sealed class ReplaceProductSkusCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public ReplaceProductSkusCommandValidator() - { - RuleFor(x => x.ProductId).GreaterThan(0); - RuleForEach(x => x.Skus).ChildRules(sku => - { - sku.RuleFor(x => x.SkuCode).NotEmpty().MaximumLength(64); - sku.RuleFor(x => x.Price).GreaterThan(0); - sku.RuleFor(x => x.OriginalPrice).GreaterThan(0).When(x => x.OriginalPrice.HasValue); - sku.RuleFor(x => x.StockQuantity).GreaterThanOrEqualTo(0).When(x => x.StockQuantity.HasValue); - sku.RuleFor(x => x.SortOrder).GreaterThanOrEqualTo(0); - }); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Validators/SearchProductsQueryValidator.cs b/src/Application/TakeoutSaaS.Application/App/Products/Validators/SearchProductsQueryValidator.cs deleted file mode 100644 index 23e3962..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Validators/SearchProductsQueryValidator.cs +++ /dev/null @@ -1,20 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Products.Queries; - -namespace TakeoutSaaS.Application.App.Products.Validators; - -/// -/// 商品列表查询验证器。 -/// -public sealed class SearchProductsQueryValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public SearchProductsQueryValidator() - { - RuleFor(x => x.Page).GreaterThan(0); - RuleFor(x => x.PageSize).InclusiveBetween(1, 200); - RuleFor(x => x.SortBy).MaximumLength(64); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Validators/UnpublishProductCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Products/Validators/UnpublishProductCommandValidator.cs deleted file mode 100644 index 1ee952c..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Validators/UnpublishProductCommandValidator.cs +++ /dev/null @@ -1,19 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Products.Commands; - -namespace TakeoutSaaS.Application.App.Products.Validators; - -/// -/// 下架商品命令验证器。 -/// -public sealed class UnpublishProductCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public UnpublishProductCommandValidator() - { - RuleFor(x => x.ProductId).GreaterThan(0); - RuleFor(x => x.Reason).MaximumLength(256); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Products/Validators/UpdateProductCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Products/Validators/UpdateProductCommandValidator.cs deleted file mode 100644 index 20200f2..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Products/Validators/UpdateProductCommandValidator.cs +++ /dev/null @@ -1,30 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Products.Commands; - -namespace TakeoutSaaS.Application.App.Products.Validators; - -/// -/// 更新商品命令验证器。 -/// -public sealed class UpdateProductCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public UpdateProductCommandValidator() - { - RuleFor(x => x.ProductId).GreaterThan(0); - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.CategoryId).GreaterThan(0); - RuleFor(x => x.SpuCode).NotEmpty().MaximumLength(32); - RuleFor(x => x.Name).NotEmpty().MaximumLength(128); - RuleFor(x => x.Subtitle).MaximumLength(256); - RuleFor(x => x.Unit).MaximumLength(16); - RuleFor(x => x.Price).GreaterThanOrEqualTo(0); - RuleFor(x => x.OriginalPrice).GreaterThanOrEqualTo(0).When(x => x.OriginalPrice.HasValue); - RuleFor(x => x.StockQuantity).GreaterThanOrEqualTo(0).When(x => x.StockQuantity.HasValue); - RuleFor(x => x.MaxQuantityPerOrder).GreaterThan(0).When(x => x.MaxQuantityPerOrder.HasValue); - RuleFor(x => x.CoverImage).MaximumLength(256); - RuleFor(x => x.GalleryImages).MaximumLength(1024); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Commands/CreateQuotaPackageCommand.cs b/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Commands/CreateQuotaPackageCommand.cs deleted file mode 100644 index 7c8de9e..0000000 --- a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Commands/CreateQuotaPackageCommand.cs +++ /dev/null @@ -1,46 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.QuotaPackages.Dto; -using TakeoutSaaS.Domain.Tenants.Enums; - -namespace TakeoutSaaS.Application.App.QuotaPackages.Commands; - -/// -/// 创建配额包命令。 -/// -public sealed record CreateQuotaPackageCommand : IRequest -{ - /// - /// 配额包名称。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 配额类型。 - /// - public TenantQuotaType QuotaType { get; init; } - - /// - /// 配额数值。 - /// - public decimal QuotaValue { get; init; } - - /// - /// 价格。 - /// - public decimal Price { get; init; } - - /// - /// 是否上架。 - /// - public bool IsActive { get; init; } = true; - - /// - /// 排序。 - /// - public int SortOrder { get; init; } = 0; - - /// - /// 描述。 - /// - public string? Description { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Commands/DeleteQuotaPackageCommand.cs b/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Commands/DeleteQuotaPackageCommand.cs deleted file mode 100644 index 62c8f3f..0000000 --- a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Commands/DeleteQuotaPackageCommand.cs +++ /dev/null @@ -1,14 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.App.QuotaPackages.Commands; - -/// -/// 删除配额包命令。 -/// -public sealed record DeleteQuotaPackageCommand : IRequest -{ - /// - /// 配额包 ID。 - /// - public long QuotaPackageId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Commands/PurchaseQuotaPackageCommand.cs b/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Commands/PurchaseQuotaPackageCommand.cs deleted file mode 100644 index 3485036..0000000 --- a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Commands/PurchaseQuotaPackageCommand.cs +++ /dev/null @@ -1,30 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.QuotaPackages.Dto; - -namespace TakeoutSaaS.Application.App.QuotaPackages.Commands; - -/// -/// 为租户购买配额包命令。 -/// -public sealed record PurchaseQuotaPackageCommand : IRequest -{ - /// - /// 租户 ID。 - /// - public long TenantId { get; init; } - - /// - /// 配额包 ID。 - /// - public long QuotaPackageId { get; init; } - - /// - /// 过期时间(可选)。 - /// - public DateTime? ExpiredAt { get; init; } - - /// - /// 备注。 - /// - public string? Notes { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Commands/UpdateQuotaPackageCommand.cs b/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Commands/UpdateQuotaPackageCommand.cs deleted file mode 100644 index f6f43c3..0000000 --- a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Commands/UpdateQuotaPackageCommand.cs +++ /dev/null @@ -1,51 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.QuotaPackages.Dto; -using TakeoutSaaS.Domain.Tenants.Enums; - -namespace TakeoutSaaS.Application.App.QuotaPackages.Commands; - -/// -/// 更新配额包命令。 -/// -public sealed record UpdateQuotaPackageCommand : IRequest -{ - /// - /// 配额包 ID。 - /// - public long QuotaPackageId { get; init; } - - /// - /// 配额包名称。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 配额类型。 - /// - public TenantQuotaType QuotaType { get; init; } - - /// - /// 配额数值。 - /// - public decimal QuotaValue { get; init; } - - /// - /// 价格。 - /// - public decimal Price { get; init; } - - /// - /// 是否上架。 - /// - public bool IsActive { get; init; } = true; - - /// - /// 排序。 - /// - public int SortOrder { get; init; } = 0; - - /// - /// 描述。 - /// - public string? Description { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Commands/UpdateQuotaPackageStatusCommand.cs b/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Commands/UpdateQuotaPackageStatusCommand.cs deleted file mode 100644 index 4a0fdb0..0000000 --- a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Commands/UpdateQuotaPackageStatusCommand.cs +++ /dev/null @@ -1,19 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.App.QuotaPackages.Commands; - -/// -/// 更新配额包状态命令(上架/下架)。 -/// -public sealed record UpdateQuotaPackageStatusCommand : IRequest -{ - /// - /// 配额包 ID。 - /// - public long QuotaPackageId { get; init; } - - /// - /// 是否上架。 - /// - public bool IsActive { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Dto/QuotaPackageDto.cs b/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Dto/QuotaPackageDto.cs deleted file mode 100644 index f710e8c..0000000 --- a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Dto/QuotaPackageDto.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.QuotaPackages.Dto; - -/// -/// 配额包 DTO。 -/// -public sealed record QuotaPackageDto -{ - /// - /// 配额包 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 配额包名称。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 配额类型。 - /// - public TenantQuotaType QuotaType { get; init; } - - /// - /// 配额数值。 - /// - public decimal QuotaValue { get; init; } - - /// - /// 价格。 - /// - public decimal Price { get; init; } - - /// - /// 是否上架。 - /// - public bool IsActive { get; init; } - - /// - /// 排序。 - /// - public int SortOrder { get; init; } - - /// - /// 描述。 - /// - public string? Description { get; init; } - - /// - /// 创建时间。 - /// - public DateTime CreatedAt { get; init; } - - /// - /// 更新时间。 - /// - public DateTime? UpdatedAt { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Dto/QuotaPackageListDto.cs b/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Dto/QuotaPackageListDto.cs deleted file mode 100644 index 9dd8fdf..0000000 --- a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Dto/QuotaPackageListDto.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.QuotaPackages.Dto; - -/// -/// 配额包列表 DTO。 -/// -public sealed record QuotaPackageListDto -{ - /// - /// 配额包 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 配额包名称。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 配额类型。 - /// - public TenantQuotaType QuotaType { get; init; } - - /// - /// 配额数值。 - /// - public decimal QuotaValue { get; init; } - - /// - /// 价格。 - /// - public decimal Price { get; init; } - - /// - /// 是否上架。 - /// - public bool IsActive { get; init; } - - /// - /// 排序。 - /// - public int SortOrder { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Dto/TenantQuotaPurchaseDto.cs b/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Dto/TenantQuotaPurchaseDto.cs deleted file mode 100644 index 2ce1bb4..0000000 --- a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Dto/TenantQuotaPurchaseDto.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.QuotaPackages.Dto; - -/// -/// 租户配额购买记录 DTO。 -/// -public sealed record TenantQuotaPurchaseDto -{ - /// - /// 购买记录 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 租户 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 配额包 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long QuotaPackageId { get; init; } - - /// - /// 配额包名称。 - /// - public string QuotaPackageName { get; init; } = string.Empty; - - /// - /// 配额类型。 - /// - public TenantQuotaType QuotaType { get; init; } - - /// - /// 购买时的配额值。 - /// - public decimal QuotaValue { get; init; } - - /// - /// 购买价格。 - /// - public decimal Price { get; init; } - - /// - /// 购买时间。 - /// - public DateTime PurchasedAt { get; init; } - - /// - /// 过期时间(可选)。 - /// - public DateTime? ExpiredAt { get; init; } - - /// - /// 备注。 - /// - public string? Notes { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Dto/TenantQuotaUsageDto.cs b/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Dto/TenantQuotaUsageDto.cs deleted file mode 100644 index a651fd8..0000000 --- a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Dto/TenantQuotaUsageDto.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.QuotaPackages.Dto; - -/// -/// 租户配额使用情况 DTO。 -/// -public sealed record TenantQuotaUsageDto -{ - /// - /// 租户 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 配额类型。 - /// - public TenantQuotaType QuotaType { get; init; } - - /// - /// 配额上限。 - /// - public decimal LimitValue { get; init; } - - /// - /// 已使用值。 - /// - public decimal UsedValue { get; init; } - - /// - /// 剩余值。 - /// - public decimal RemainingValue { get; init; } - - /// - /// 配额刷新周期。 - /// - public string? ResetCycle { get; init; } - - /// - /// 最近一次重置时间。 - /// - public DateTime? LastResetAt { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/CreateQuotaPackageCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/CreateQuotaPackageCommandHandler.cs deleted file mode 100644 index 28c9b3a..0000000 --- a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/CreateQuotaPackageCommandHandler.cs +++ /dev/null @@ -1,54 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.QuotaPackages.Commands; -using TakeoutSaaS.Application.App.QuotaPackages.Dto; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Ids; - -namespace TakeoutSaaS.Application.App.QuotaPackages.Handlers; - -/// -/// 创建配额包命令处理器。 -/// -public sealed class CreateQuotaPackageCommandHandler( - IQuotaPackageRepository quotaPackageRepository, - IIdGenerator idGenerator) - : IRequestHandler -{ - /// - public async Task Handle(CreateQuotaPackageCommand request, CancellationToken cancellationToken) - { - // 1. 创建配额包实体 - var quotaPackage = new QuotaPackage - { - Id = idGenerator.NextId(), - Name = request.Name, - QuotaType = request.QuotaType, - QuotaValue = request.QuotaValue, - Price = request.Price, - IsActive = request.IsActive, - SortOrder = request.SortOrder, - Description = request.Description, - CreatedAt = DateTime.UtcNow - }; - - // 2. 保存到数据库 - await quotaPackageRepository.AddAsync(quotaPackage, cancellationToken); - await quotaPackageRepository.SaveChangesAsync(cancellationToken); - - // 3. 返回 DTO - return new QuotaPackageDto - { - Id = quotaPackage.Id, - Name = quotaPackage.Name, - QuotaType = quotaPackage.QuotaType, - QuotaValue = quotaPackage.QuotaValue, - Price = quotaPackage.Price, - IsActive = quotaPackage.IsActive, - SortOrder = quotaPackage.SortOrder, - Description = quotaPackage.Description, - CreatedAt = quotaPackage.CreatedAt, - UpdatedAt = quotaPackage.UpdatedAt - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/DeleteQuotaPackageCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/DeleteQuotaPackageCommandHandler.cs deleted file mode 100644 index 1180d7e..0000000 --- a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/DeleteQuotaPackageCommandHandler.cs +++ /dev/null @@ -1,29 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.QuotaPackages.Commands; -using TakeoutSaaS.Domain.Tenants.Repositories; - -namespace TakeoutSaaS.Application.App.QuotaPackages.Handlers; - -/// -/// 删除配额包命令处理器。 -/// -public sealed class DeleteQuotaPackageCommandHandler(IQuotaPackageRepository quotaPackageRepository) - : IRequestHandler -{ - /// - public async Task Handle(DeleteQuotaPackageCommand request, CancellationToken cancellationToken) - { - // 1. 软删除配额包 - var deleted = await quotaPackageRepository.SoftDeleteAsync(request.QuotaPackageId, cancellationToken); - - if (!deleted) - { - return false; - } - - // 2. 保存变更 - await quotaPackageRepository.SaveChangesAsync(cancellationToken); - - return true; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/GetQuotaPackageListQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/GetQuotaPackageListQueryHandler.cs deleted file mode 100644 index a61d883..0000000 --- a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/GetQuotaPackageListQueryHandler.cs +++ /dev/null @@ -1,41 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.QuotaPackages.Dto; -using TakeoutSaaS.Application.App.QuotaPackages.Queries; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.App.QuotaPackages.Handlers; - -/// -/// 获取配额包列表查询处理器。 -/// -public sealed class GetQuotaPackageListQueryHandler(IQuotaPackageRepository quotaPackageRepository) - : IRequestHandler> -{ - /// - public async Task> Handle(GetQuotaPackageListQuery request, CancellationToken cancellationToken) - { - // 1. 分页查询 - var (items, total) = await quotaPackageRepository.SearchPagedAsync( - request.QuotaType, - request.IsActive, - request.Page, - request.PageSize, - cancellationToken); - - // 2. 映射为 DTO - var dtos = items.Select(x => new QuotaPackageListDto - { - Id = x.Id, - Name = x.Name, - QuotaType = x.QuotaType, - QuotaValue = x.QuotaValue, - Price = x.Price, - IsActive = x.IsActive, - SortOrder = x.SortOrder - }).ToList(); - - // 3. 返回分页结果 - return new PagedResult(dtos, request.Page, request.PageSize, total); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/GetTenantQuotaPurchasesQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/GetTenantQuotaPurchasesQueryHandler.cs deleted file mode 100644 index 1b232d3..0000000 --- a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/GetTenantQuotaPurchasesQueryHandler.cs +++ /dev/null @@ -1,43 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.QuotaPackages.Dto; -using TakeoutSaaS.Application.App.QuotaPackages.Queries; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.App.QuotaPackages.Handlers; - -/// -/// 获取租户配额购买记录查询处理器。 -/// -public sealed class GetTenantQuotaPurchasesQueryHandler(IQuotaPackageRepository quotaPackageRepository) - : IRequestHandler> -{ - /// - public async Task> Handle(GetTenantQuotaPurchasesQuery request, CancellationToken cancellationToken) - { - // 1. 分页查询购买记录 - var (items, total) = await quotaPackageRepository.GetPurchasesPagedAsync( - request.TenantId, - request.Page, - request.PageSize, - cancellationToken); - - // 2. 映射为 DTO - var dtos = items.Select(x => new TenantQuotaPurchaseDto - { - Id = x.Purchase.Id, - TenantId = x.Purchase.TenantId, - QuotaPackageId = x.Purchase.QuotaPackageId, - QuotaPackageName = x.Package.Name, - QuotaType = x.Package.QuotaType, - QuotaValue = x.Purchase.QuotaValue, - Price = x.Purchase.Price, - PurchasedAt = x.Purchase.PurchasedAt, - ExpiredAt = x.Purchase.ExpiredAt, - Notes = x.Purchase.Notes - }).ToList(); - - // 3. 返回分页结果 - return new PagedResult(dtos, request.Page, request.PageSize, total); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/GetTenantQuotaUsageQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/GetTenantQuotaUsageQueryHandler.cs deleted file mode 100644 index ee246b6..0000000 --- a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/GetTenantQuotaUsageQueryHandler.cs +++ /dev/null @@ -1,35 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.QuotaPackages.Dto; -using TakeoutSaaS.Application.App.QuotaPackages.Queries; -using TakeoutSaaS.Domain.Tenants.Repositories; - -namespace TakeoutSaaS.Application.App.QuotaPackages.Handlers; - -/// -/// 获取租户配额使用情况查询处理器。 -/// -public sealed class GetTenantQuotaUsageQueryHandler(IQuotaPackageRepository quotaPackageRepository) - : IRequestHandler> -{ - /// - public async Task> Handle(GetTenantQuotaUsageQuery request, CancellationToken cancellationToken) - { - // 1. 查询配额使用情况 - var items = await quotaPackageRepository.GetUsageByTenantAsync( - request.TenantId, - request.QuotaType, - cancellationToken); - - // 2. 映射为 DTO - return items.Select(x => new TenantQuotaUsageDto - { - TenantId = x.TenantId, - QuotaType = x.QuotaType, - LimitValue = x.LimitValue, - UsedValue = x.UsedValue, - RemainingValue = x.LimitValue - x.UsedValue, - ResetCycle = x.ResetCycle, - LastResetAt = x.LastResetAt - }).ToList(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/PurchaseQuotaPackageCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/PurchaseQuotaPackageCommandHandler.cs deleted file mode 100644 index 65d7a68..0000000 --- a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/PurchaseQuotaPackageCommandHandler.cs +++ /dev/null @@ -1,88 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.QuotaPackages.Commands; -using TakeoutSaaS.Application.App.QuotaPackages.Dto; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Ids; - -namespace TakeoutSaaS.Application.App.QuotaPackages.Handlers; - -/// -/// 购买配额包命令处理器。 -/// -public sealed class PurchaseQuotaPackageCommandHandler( - IQuotaPackageRepository quotaPackageRepository, - ITenantQuotaUsageHistoryRepository quotaUsageHistoryRepository, - IIdGenerator idGenerator) - : IRequestHandler -{ - /// - public async Task Handle(PurchaseQuotaPackageCommand request, CancellationToken cancellationToken) - { - // 1. 查找配额包 - var quotaPackage = await quotaPackageRepository.FindByIdAsync(request.QuotaPackageId, cancellationToken); - - if (quotaPackage == null) - { - throw new InvalidOperationException("配额包不存在"); - } - - // 2. 创建购买记录 - var purchase = new TenantQuotaPackagePurchase - { - Id = idGenerator.NextId(), - TenantId = request.TenantId, - QuotaPackageId = request.QuotaPackageId, - QuotaValue = quotaPackage.QuotaValue, - Price = quotaPackage.Price, - PurchasedAt = DateTime.UtcNow, - ExpiredAt = request.ExpiredAt, - Notes = request.Notes, - CreatedAt = DateTime.UtcNow - }; - - // 3. 保存购买记录 - await quotaPackageRepository.AddPurchaseAsync(purchase, cancellationToken); - - // 4. 更新租户配额(根据配额类型更新对应配额) - var quotaUsage = await quotaPackageRepository.FindUsageAsync(request.TenantId, quotaPackage.QuotaType, cancellationToken); - - if (quotaUsage != null) - { - var beforeLimit = quotaUsage.LimitValue; - quotaUsage.LimitValue += quotaPackage.QuotaValue; - await quotaPackageRepository.UpdateUsageAsync(quotaUsage, cancellationToken); - - // 4.1 记录配额变更历史(购买配额包视为“剩余增加”) - await quotaUsageHistoryRepository.AddAsync(new TenantQuotaUsageHistory - { - TenantId = request.TenantId, - QuotaType = quotaPackage.QuotaType, - UsedValue = quotaUsage.UsedValue, - LimitValue = quotaUsage.LimitValue, - RecordedAt = DateTime.UtcNow, - ChangeType = TenantQuotaUsageHistoryChangeType.Increase, - ChangeAmount = quotaUsage.LimitValue - beforeLimit, - ChangeReason = $"购买配额包:{quotaPackage.Name}" - }, cancellationToken); - } - - await quotaPackageRepository.SaveChangesAsync(cancellationToken); - - // 5. 返回 DTO - return new TenantQuotaPurchaseDto - { - Id = purchase.Id, - TenantId = purchase.TenantId, - QuotaPackageId = purchase.QuotaPackageId, - QuotaPackageName = quotaPackage.Name, - QuotaType = quotaPackage.QuotaType, - QuotaValue = purchase.QuotaValue, - Price = purchase.Price, - PurchasedAt = purchase.PurchasedAt, - ExpiredAt = purchase.ExpiredAt, - Notes = purchase.Notes - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/UpdateQuotaPackageCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/UpdateQuotaPackageCommandHandler.cs deleted file mode 100644 index 5e57207..0000000 --- a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/UpdateQuotaPackageCommandHandler.cs +++ /dev/null @@ -1,54 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.QuotaPackages.Commands; -using TakeoutSaaS.Application.App.QuotaPackages.Dto; -using TakeoutSaaS.Domain.Tenants.Repositories; - -namespace TakeoutSaaS.Application.App.QuotaPackages.Handlers; - -/// -/// 更新配额包命令处理器。 -/// -public sealed class UpdateQuotaPackageCommandHandler(IQuotaPackageRepository quotaPackageRepository) - : IRequestHandler -{ - /// - public async Task Handle(UpdateQuotaPackageCommand request, CancellationToken cancellationToken) - { - // 1. 查找配额包 - var quotaPackage = await quotaPackageRepository.FindByIdAsync(request.QuotaPackageId, cancellationToken); - - if (quotaPackage == null) - { - return null; - } - - // 2. 更新配额包 - quotaPackage.Name = request.Name; - quotaPackage.QuotaType = request.QuotaType; - quotaPackage.QuotaValue = request.QuotaValue; - quotaPackage.Price = request.Price; - quotaPackage.IsActive = request.IsActive; - quotaPackage.SortOrder = request.SortOrder; - quotaPackage.Description = request.Description; - quotaPackage.UpdatedAt = DateTime.UtcNow; - - // 3. 保存到数据库 - await quotaPackageRepository.UpdateAsync(quotaPackage, cancellationToken); - await quotaPackageRepository.SaveChangesAsync(cancellationToken); - - // 4. 返回 DTO - return new QuotaPackageDto - { - Id = quotaPackage.Id, - Name = quotaPackage.Name, - QuotaType = quotaPackage.QuotaType, - QuotaValue = quotaPackage.QuotaValue, - Price = quotaPackage.Price, - IsActive = quotaPackage.IsActive, - SortOrder = quotaPackage.SortOrder, - Description = quotaPackage.Description, - CreatedAt = quotaPackage.CreatedAt, - UpdatedAt = quotaPackage.UpdatedAt - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/UpdateQuotaPackageStatusCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/UpdateQuotaPackageStatusCommandHandler.cs deleted file mode 100644 index e5ea40b..0000000 --- a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Handlers/UpdateQuotaPackageStatusCommandHandler.cs +++ /dev/null @@ -1,34 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.QuotaPackages.Commands; -using TakeoutSaaS.Domain.Tenants.Repositories; - -namespace TakeoutSaaS.Application.App.QuotaPackages.Handlers; - -/// -/// 更新配额包状态命令处理器。 -/// -public sealed class UpdateQuotaPackageStatusCommandHandler(IQuotaPackageRepository quotaPackageRepository) - : IRequestHandler -{ - /// - public async Task Handle(UpdateQuotaPackageStatusCommand request, CancellationToken cancellationToken) - { - // 1. 查找配额包 - var quotaPackage = await quotaPackageRepository.FindByIdAsync(request.QuotaPackageId, cancellationToken); - - if (quotaPackage == null) - { - return false; - } - - // 2. 更新状态 - quotaPackage.IsActive = request.IsActive; - quotaPackage.UpdatedAt = DateTime.UtcNow; - - // 3. 保存到数据库 - await quotaPackageRepository.UpdateAsync(quotaPackage, cancellationToken); - await quotaPackageRepository.SaveChangesAsync(cancellationToken); - - return true; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Queries/GetQuotaPackageListQuery.cs b/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Queries/GetQuotaPackageListQuery.cs deleted file mode 100644 index 538d1ef..0000000 --- a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Queries/GetQuotaPackageListQuery.cs +++ /dev/null @@ -1,32 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.QuotaPackages.Dto; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.App.QuotaPackages.Queries; - -/// -/// 获取配额包列表查询。 -/// -public sealed record GetQuotaPackageListQuery : IRequest> -{ - /// - /// 配额类型(可选筛选)。 - /// - public TenantQuotaType? QuotaType { get; init; } - - /// - /// 状态(可选筛选)。 - /// - public bool? IsActive { get; init; } - - /// - /// 页码。 - /// - public int Page { get; init; } = 1; - - /// - /// 每页大小。 - /// - public int PageSize { get; init; } = 20; -} diff --git a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Queries/GetTenantQuotaPurchasesQuery.cs b/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Queries/GetTenantQuotaPurchasesQuery.cs deleted file mode 100644 index 56348e6..0000000 --- a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Queries/GetTenantQuotaPurchasesQuery.cs +++ /dev/null @@ -1,26 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.QuotaPackages.Dto; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.App.QuotaPackages.Queries; - -/// -/// 获取租户配额购买记录查询。 -/// -public sealed record GetTenantQuotaPurchasesQuery : IRequest> -{ - /// - /// 租户 ID。 - /// - public long TenantId { get; init; } - - /// - /// 页码。 - /// - public int Page { get; init; } = 1; - - /// - /// 每页大小。 - /// - public int PageSize { get; init; } = 20; -} diff --git a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Queries/GetTenantQuotaUsageQuery.cs b/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Queries/GetTenantQuotaUsageQuery.cs deleted file mode 100644 index f5b395c..0000000 --- a/src/Application/TakeoutSaaS.Application/App/QuotaPackages/Queries/GetTenantQuotaUsageQuery.cs +++ /dev/null @@ -1,21 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.QuotaPackages.Dto; -using TakeoutSaaS.Domain.Tenants.Enums; - -namespace TakeoutSaaS.Application.App.QuotaPackages.Queries; - -/// -/// 获取租户配额使用情况查询。 -/// -public sealed record GetTenantQuotaUsageQuery : IRequest> -{ - /// - /// 租户 ID。 - /// - public long TenantId { get; init; } - - /// - /// 配额类型(可选筛选)。 - /// - public TenantQuotaType? QuotaType { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Statistics/Dto/ExpiringSubscriptionDto.cs b/src/Application/TakeoutSaaS.Application/App/Statistics/Dto/ExpiringSubscriptionDto.cs deleted file mode 100644 index c9a6d30..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Statistics/Dto/ExpiringSubscriptionDto.cs +++ /dev/null @@ -1,49 +0,0 @@ -using TakeoutSaaS.Domain.Tenants.Enums; - -namespace TakeoutSaaS.Application.App.Statistics.Dto; - -/// -/// 即将到期的订阅项。 -/// -public record ExpiringSubscriptionDto -{ - /// - /// 订阅ID。 - /// - public long Id { get; init; } - - /// - /// 租户ID。 - /// - public string TenantId { get; init; } = string.Empty; - - /// - /// 租户名称。 - /// - public string TenantName { get; init; } = string.Empty; - - /// - /// 套餐名称。 - /// - public string PackageName { get; init; } = string.Empty; - - /// - /// 订阅状态。 - /// - public SubscriptionStatus Status { get; init; } - - /// - /// 到期时间。 - /// - public DateTime EffectiveTo { get; init; } - - /// - /// 剩余天数。 - /// - public int DaysRemaining { get; init; } - - /// - /// 是否开启自动续费。 - /// - public bool AutoRenew { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Statistics/Dto/QuotaUsageRankingDto.cs b/src/Application/TakeoutSaaS.Application/App/Statistics/Dto/QuotaUsageRankingDto.cs deleted file mode 100644 index 57f53c2..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Statistics/Dto/QuotaUsageRankingDto.cs +++ /dev/null @@ -1,50 +0,0 @@ -using TakeoutSaaS.Domain.Tenants.Enums; - -namespace TakeoutSaaS.Application.App.Statistics.Dto; - -/// -/// 配额使用排行。 -/// -public record QuotaUsageRankingDto -{ - /// - /// 配额类型。 - /// - public TenantQuotaType QuotaType { get; init; } - - /// - /// 排行列表。 - /// - public IReadOnlyList Rankings { get; init; } = Array.Empty(); -} - -/// -/// 配额使用排行项。 -/// -public record QuotaUsageRankItem -{ - /// - /// 租户ID。 - /// - public string TenantId { get; init; } = string.Empty; - - /// - /// 租户名称。 - /// - public string TenantName { get; init; } = string.Empty; - - /// - /// 已使用值。 - /// - public decimal UsedValue { get; init; } - - /// - /// 限制值。 - /// - public decimal LimitValue { get; init; } - - /// - /// 使用百分比。 - /// - public decimal UsagePercentage { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Statistics/Dto/RevenueStatisticsDto.cs b/src/Application/TakeoutSaaS.Application/App/Statistics/Dto/RevenueStatisticsDto.cs deleted file mode 100644 index ceb604f..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Statistics/Dto/RevenueStatisticsDto.cs +++ /dev/null @@ -1,53 +0,0 @@ -namespace TakeoutSaaS.Application.App.Statistics.Dto; - -/// -/// 收入统计。 -/// -public record RevenueStatisticsDto -{ - /// - /// 总收入。 - /// - public decimal TotalRevenue { get; init; } - - /// - /// 本月收入。 - /// - public decimal MonthlyRevenue { get; init; } - - /// - /// 本季度收入。 - /// - public decimal QuarterlyRevenue { get; init; } - - /// - /// 月度收入明细。 - /// - public IReadOnlyList MonthlyDetails { get; init; } = Array.Empty(); -} - -/// -/// 月度收入项。 -/// -public record MonthlyRevenueItem -{ - /// - /// 年份。 - /// - public int Year { get; init; } - - /// - /// 月份。 - /// - public int Month { get; init; } - - /// - /// 收入金额。 - /// - public decimal Amount { get; init; } - - /// - /// 账单数量。 - /// - public int BillCount { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Statistics/Dto/SubscriptionOverviewDto.cs b/src/Application/TakeoutSaaS.Application/App/Statistics/Dto/SubscriptionOverviewDto.cs deleted file mode 100644 index 9323faa..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Statistics/Dto/SubscriptionOverviewDto.cs +++ /dev/null @@ -1,42 +0,0 @@ -namespace TakeoutSaaS.Application.App.Statistics.Dto; - -/// -/// 订阅概览。 -/// -public record SubscriptionOverviewDto -{ - /// - /// 活跃订阅总数。 - /// - public int TotalActive { get; init; } - - /// - /// 7天内到期数量。 - /// - public int ExpiringIn7Days { get; init; } - - /// - /// 3天内到期数量。 - /// - public int ExpiringIn3Days { get; init; } - - /// - /// 1天内到期数量。 - /// - public int ExpiringIn1Day { get; init; } - - /// - /// 已过期数量。 - /// - public int Expired { get; init; } - - /// - /// 待激活数量。 - /// - public int Pending { get; init; } - - /// - /// 已暂停数量。 - /// - public int Suspended { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Statistics/Handlers/GetExpiringSubscriptionsQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Statistics/Handlers/GetExpiringSubscriptionsQueryHandler.cs deleted file mode 100644 index a913aac..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Statistics/Handlers/GetExpiringSubscriptionsQueryHandler.cs +++ /dev/null @@ -1,38 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Statistics.Dto; -using TakeoutSaaS.Application.App.Statistics.Queries; -using TakeoutSaaS.Domain.Tenants.Repositories; - -namespace TakeoutSaaS.Application.App.Statistics.Handlers; - -/// -/// 获取即将到期的订阅列表处理器。 -/// -public sealed class GetExpiringSubscriptionsQueryHandler(IStatisticsRepository statisticsRepository) - : IRequestHandler> -{ - /// - public async Task> Handle(GetExpiringSubscriptionsQuery request, CancellationToken cancellationToken) - { - var now = DateTime.UtcNow; - - // 查询即将到期的订阅 - var items = await statisticsRepository.GetExpiringSubscriptionsAsync( - request.DaysAhead, - request.OnlyWithoutAutoRenew, - cancellationToken); - - // 映射为 DTO - return items.Select(x => new ExpiringSubscriptionDto - { - Id = x.Subscription.Id, - TenantId = x.Subscription.TenantId.ToString(), - TenantName = x.TenantName, - PackageName = x.PackageName, - Status = x.Subscription.Status, - EffectiveTo = x.Subscription.EffectiveTo, - DaysRemaining = (int)(x.Subscription.EffectiveTo - now).TotalDays, - AutoRenew = x.Subscription.AutoRenew - }).ToList(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Statistics/Handlers/GetQuotaUsageRankingQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Statistics/Handlers/GetQuotaUsageRankingQueryHandler.cs deleted file mode 100644 index b6fc116..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Statistics/Handlers/GetQuotaUsageRankingQueryHandler.cs +++ /dev/null @@ -1,39 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Statistics.Dto; -using TakeoutSaaS.Application.App.Statistics.Queries; -using TakeoutSaaS.Domain.Tenants.Repositories; - -namespace TakeoutSaaS.Application.App.Statistics.Handlers; - -/// -/// 获取配额使用排行处理器。 -/// -public sealed class GetQuotaUsageRankingQueryHandler(IStatisticsRepository statisticsRepository) - : IRequestHandler -{ - /// - public async Task Handle(GetQuotaUsageRankingQuery request, CancellationToken cancellationToken) - { - // 查询指定类型的配额使用排行 - var items = await statisticsRepository.GetQuotaUsageRankingAsync( - request.QuotaType, - request.TopN, - cancellationToken); - - // 映射为 DTO - var rankings = items.Select(x => new QuotaUsageRankItem - { - TenantId = x.TenantId.ToString(), - TenantName = x.TenantName, - UsedValue = x.UsedValue, - LimitValue = x.LimitValue, - UsagePercentage = x.UsagePercentage - }).ToList(); - - return new QuotaUsageRankingDto - { - QuotaType = request.QuotaType, - Rankings = rankings - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Statistics/Handlers/GetRevenueStatisticsQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Statistics/Handlers/GetRevenueStatisticsQueryHandler.cs deleted file mode 100644 index 55cee9f..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Statistics/Handlers/GetRevenueStatisticsQueryHandler.cs +++ /dev/null @@ -1,71 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Statistics.Dto; -using TakeoutSaaS.Application.App.Statistics.Queries; -using TakeoutSaaS.Domain.Tenants.Repositories; - -namespace TakeoutSaaS.Application.App.Statistics.Handlers; - -/// -/// 获取收入统计处理器。 -/// -public sealed class GetRevenueStatisticsQueryHandler(IStatisticsRepository statisticsRepository) - : IRequestHandler -{ - /// - public async Task Handle(GetRevenueStatisticsQuery request, CancellationToken cancellationToken) - { - var now = DateTime.UtcNow; - var currentMonth = new DateTime(now.Year, now.Month, 1); - var currentQuarter = GetQuarterStart(now); - var startMonth = currentMonth.AddMonths(-request.MonthsCount + 1); - - // 查询所有已付款的账单 - var bills = await statisticsRepository.GetPaidBillsAsync(cancellationToken); - - // 总收入 - var totalRevenue = bills.Sum(b => b.AmountPaid); - - // 本月收入 - var monthlyRevenue = bills - .Where(b => b.PeriodStart >= currentMonth) - .Sum(b => b.AmountPaid); - - // 本季度收入 - var quarterlyRevenue = bills - .Where(b => b.PeriodStart >= currentQuarter) - .Sum(b => b.AmountPaid); - - // 月度收入明细 - var monthlyDetails = bills - .Where(b => b.PeriodStart >= startMonth) - .GroupBy(b => new { b.PeriodStart.Year, b.PeriodStart.Month }) - .Select(g => new MonthlyRevenueItem - { - Year = g.Key.Year, - Month = g.Key.Month, - Amount = g.Sum(b => b.AmountPaid), - BillCount = g.Count() - }) - .OrderBy(m => m.Year) - .ThenBy(m => m.Month) - .ToList(); - - return new RevenueStatisticsDto - { - TotalRevenue = totalRevenue, - MonthlyRevenue = monthlyRevenue, - QuarterlyRevenue = quarterlyRevenue, - MonthlyDetails = monthlyDetails - }; - } - - /// - /// 获取季度开始时间。 - /// - private static DateTime GetQuarterStart(DateTime date) - { - var quarter = (date.Month - 1) / 3; - var quarterStartMonth = quarter * 3 + 1; - return new DateTime(date.Year, quarterStartMonth, 1); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Statistics/Handlers/GetSubscriptionOverviewQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Statistics/Handlers/GetSubscriptionOverviewQueryHandler.cs deleted file mode 100644 index 054044b..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Statistics/Handlers/GetSubscriptionOverviewQueryHandler.cs +++ /dev/null @@ -1,49 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Statistics.Dto; -using TakeoutSaaS.Application.App.Statistics.Queries; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; - -namespace TakeoutSaaS.Application.App.Statistics.Handlers; - -/// -/// 获取订阅概览统计处理器。 -/// -public sealed class GetSubscriptionOverviewQueryHandler(IStatisticsRepository statisticsRepository) - : IRequestHandler -{ - /// - public async Task Handle(GetSubscriptionOverviewQuery request, CancellationToken cancellationToken) - { - var now = DateTime.UtcNow; - var in7Days = now.AddDays(7); - var in3Days = now.AddDays(3); - var in1Day = now.AddDays(1); - - // 查询所有订阅 - var subscriptions = await statisticsRepository.GetAllSubscriptionsAsync(cancellationToken); - - // 统计各项数据 - var overview = new SubscriptionOverviewDto - { - TotalActive = subscriptions.Count(s => s.Status == SubscriptionStatus.Active), - ExpiringIn7Days = subscriptions.Count(s => - s.Status == SubscriptionStatus.Active && - s.EffectiveTo >= now && - s.EffectiveTo <= in7Days), - ExpiringIn3Days = subscriptions.Count(s => - s.Status == SubscriptionStatus.Active && - s.EffectiveTo >= now && - s.EffectiveTo <= in3Days), - ExpiringIn1Day = subscriptions.Count(s => - s.Status == SubscriptionStatus.Active && - s.EffectiveTo >= now && - s.EffectiveTo <= in1Day), - Expired = subscriptions.Count(s => s.Status == SubscriptionStatus.GracePeriod), - Pending = subscriptions.Count(s => s.Status == SubscriptionStatus.Pending), - Suspended = subscriptions.Count(s => s.Status == SubscriptionStatus.Suspended) - }; - - return overview; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Statistics/Queries/GetExpiringSubscriptionsQuery.cs b/src/Application/TakeoutSaaS.Application/App/Statistics/Queries/GetExpiringSubscriptionsQuery.cs deleted file mode 100644 index 3fcd2e6..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Statistics/Queries/GetExpiringSubscriptionsQuery.cs +++ /dev/null @@ -1,20 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Statistics.Dto; - -namespace TakeoutSaaS.Application.App.Statistics.Queries; - -/// -/// 获取即将到期的订阅列表。 -/// -public sealed record GetExpiringSubscriptionsQuery : IRequest> -{ - /// - /// 筛选天数,默认7天内到期。 - /// - public int DaysAhead { get; init; } = 7; - - /// - /// 是否只返回未开启自动续费的订阅。 - /// - public bool OnlyWithoutAutoRenew { get; init; } = false; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Statistics/Queries/GetQuotaUsageRankingQuery.cs b/src/Application/TakeoutSaaS.Application/App/Statistics/Queries/GetQuotaUsageRankingQuery.cs deleted file mode 100644 index af8d0cc..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Statistics/Queries/GetQuotaUsageRankingQuery.cs +++ /dev/null @@ -1,21 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Statistics.Dto; -using TakeoutSaaS.Domain.Tenants.Enums; - -namespace TakeoutSaaS.Application.App.Statistics.Queries; - -/// -/// 获取配额使用排行。 -/// -public sealed record GetQuotaUsageRankingQuery : IRequest -{ - /// - /// 配额类型。 - /// - public TenantQuotaType QuotaType { get; init; } - - /// - /// 返回前N条记录,默认前10。 - /// - public int TopN { get; init; } = 10; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Statistics/Queries/GetRevenueStatisticsQuery.cs b/src/Application/TakeoutSaaS.Application/App/Statistics/Queries/GetRevenueStatisticsQuery.cs deleted file mode 100644 index bda07b6..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Statistics/Queries/GetRevenueStatisticsQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Statistics.Dto; - -namespace TakeoutSaaS.Application.App.Statistics.Queries; - -/// -/// 获取收入统计。 -/// -public sealed record GetRevenueStatisticsQuery : IRequest -{ - /// - /// 统计月份数量,默认12个月。 - /// - public int MonthsCount { get; init; } = 12; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Statistics/Queries/GetSubscriptionOverviewQuery.cs b/src/Application/TakeoutSaaS.Application/App/Statistics/Queries/GetSubscriptionOverviewQuery.cs deleted file mode 100644 index 68b356a..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Statistics/Queries/GetSubscriptionOverviewQuery.cs +++ /dev/null @@ -1,11 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Statistics.Dto; - -namespace TakeoutSaaS.Application.App.Statistics.Queries; - -/// -/// 获取订阅概览统计。 -/// -public sealed record GetSubscriptionOverviewQuery : IRequest -{ -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/BatchUpdateBusinessHoursCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/BatchUpdateBusinessHoursCommand.cs deleted file mode 100644 index 2f4b50b..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/BatchUpdateBusinessHoursCommand.cs +++ /dev/null @@ -1,20 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 批量更新营业时段命令。 -/// -public sealed record BatchUpdateBusinessHoursCommand : IRequest> -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 营业时段集合。 - /// - public IReadOnlyList Items { get; init; } = []; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreBusinessHourCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreBusinessHourCommand.cs deleted file mode 100644 index 345e990..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreBusinessHourCommand.cs +++ /dev/null @@ -1,46 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Enums; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 创建营业时段命令。 -/// -public sealed record CreateStoreBusinessHourCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 星期几。 - /// - public DayOfWeek DayOfWeek { get; init; } - - /// - /// 时段类型。 - /// - public BusinessHourType HourType { get; init; } = BusinessHourType.Normal; - - /// - /// 开始时间。 - /// - public TimeSpan StartTime { get; init; } - - /// - /// 结束时间。 - /// - public TimeSpan EndTime { get; init; } - - /// - /// 容量限制。 - /// - public int? CapacityLimit { get; init; } - - /// - /// 备注。 - /// - public string? Notes { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreCommand.cs deleted file mode 100644 index 4a0f093..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreCommand.cs +++ /dev/null @@ -1,126 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Enums; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 创建门店命令。 -/// -public sealed record CreateStoreCommand : IRequest -{ - /// - /// 商户 ID。 - /// - public long MerchantId { get; init; } - - /// - /// 门店编码。 - /// - public string Code { get; init; } = string.Empty; - - /// - /// 门店名称。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 电话。 - /// - public string? Phone { get; init; } - - /// - /// 负责人。 - /// - public string? ManagerName { get; init; } - - /// - /// 状态。 - /// - public StoreStatus Status { get; init; } = StoreStatus.Closed; - - /// - /// 门头招牌图。 - /// - public string? SignboardImageUrl { get; init; } - - /// - /// 主体类型。 - /// - public StoreOwnershipType OwnershipType { get; init; } = StoreOwnershipType.SameEntity; - - /// - /// 行业类目 ID。 - /// - public long? CategoryId { get; init; } - - /// - /// 省份。 - /// - public string? Province { get; init; } - - /// - /// 城市。 - /// - public string? City { get; init; } - - /// - /// 区县。 - /// - public string? District { get; init; } - - /// - /// 详细地址。 - /// - public string? Address { get; init; } - - /// - /// 经度。 - /// - public double? Longitude { get; init; } - - /// - /// 纬度。 - /// - public double? Latitude { get; init; } - - /// - /// 公告。 - /// - public string? Announcement { get; init; } - - /// - /// 标签。 - /// - public string? Tags { get; init; } - - /// - /// 配送半径。 - /// - public decimal DeliveryRadiusKm { get; init; } - - /// - /// 支持堂食。 - /// - public bool SupportsDineIn { get; init; } = true; - - /// - /// 支持自提。 - /// - public bool SupportsPickup { get; init; } = true; - - /// - /// 支持配送。 - /// - public bool SupportsDelivery { get; init; } = true; - - /// - /// 支持预约。 - /// - public bool SupportsReservation { get; init; } - - /// - /// 支持排队叫号。 - /// - public bool SupportsQueueing { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreDeliveryZoneCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreDeliveryZoneCommand.cs deleted file mode 100644 index af1af08..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreDeliveryZoneCommand.cs +++ /dev/null @@ -1,45 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 创建配送区域命令。 -/// -public sealed record CreateStoreDeliveryZoneCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 区域名称。 - /// - public string ZoneName { get; init; } = string.Empty; - - /// - /// GeoJSON。 - /// - public string PolygonGeoJson { get; init; } = string.Empty; - - /// - /// 起送价。 - /// - public decimal? MinimumOrderAmount { get; init; } - - /// - /// 配送费。 - /// - public decimal? DeliveryFee { get; init; } - - /// - /// 预计分钟。 - /// - public int? EstimatedMinutes { get; init; } - - /// - /// 排序。 - /// - public int SortOrder { get; init; } = 100; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreEmployeeShiftCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreEmployeeShiftCommand.cs deleted file mode 100644 index 2729a6f..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreEmployeeShiftCommand.cs +++ /dev/null @@ -1,46 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Merchants.Enums; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 创建员工排班命令。 -/// -public sealed record CreateStoreEmployeeShiftCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 员工 ID。 - /// - public long StaffId { get; init; } - - /// - /// 班次日期。 - /// - public DateTime ShiftDate { get; init; } - - /// - /// 开始时间。 - /// - public TimeSpan StartTime { get; init; } - - /// - /// 结束时间。 - /// - public TimeSpan EndTime { get; init; } - - /// - /// 排班角色。 - /// - public StaffRoleType RoleType { get; init; } = StaffRoleType.FrontDesk; - - /// - /// 备注。 - /// - public string? Notes { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreHolidayCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreHolidayCommand.cs deleted file mode 100644 index 660eab2..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreHolidayCommand.cs +++ /dev/null @@ -1,51 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Enums; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 创建临时时段配置命令。 -/// -public sealed record CreateStoreHolidayCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 开始日期。 - /// - public DateTime Date { get; init; } - - /// - /// 结束日期(可选)。 - /// - public DateTime? EndDate { get; init; } - - /// - /// 是否全天。 - /// - public bool IsAllDay { get; init; } = true; - - /// - /// 开始时间(IsAllDay=false 时必填)。 - /// - public TimeSpan? StartTime { get; init; } - - /// - /// 结束时间(IsAllDay=false 时必填)。 - /// - public TimeSpan? EndTime { get; init; } - - /// - /// 覆盖类型。 - /// - public OverrideType OverrideType { get; init; } = OverrideType.Closed; - - /// - /// 说明。 - /// - public string? Reason { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStorePickupSlotCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStorePickupSlotCommand.cs deleted file mode 100644 index 0de3fa9..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStorePickupSlotCommand.cs +++ /dev/null @@ -1,50 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 创建自提档期命令。 -/// -public sealed record CreateStorePickupSlotCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 名称。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 开始时间。 - /// - public TimeSpan StartTime { get; init; } - - /// - /// 结束时间。 - /// - public TimeSpan EndTime { get; init; } - - /// - /// 截单分钟。 - /// - public int CutoffMinutes { get; init; } = 30; - - /// - /// 容量。 - /// - public int Capacity { get; init; } - - /// - /// 适用星期。 - /// - public string Weekdays { get; init; } = string.Empty; - - /// - /// 是否启用。 - /// - public bool IsEnabled { get; init; } = true; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreQualificationCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreQualificationCommand.cs deleted file mode 100644 index bf685c9..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreQualificationCommand.cs +++ /dev/null @@ -1,46 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Enums; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 创建门店资质命令。 -/// -public sealed record CreateStoreQualificationCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 资质类型。 - /// - public StoreQualificationType QualificationType { get; init; } - - /// - /// 证照文件 URL。 - /// - public string FileUrl { get; init; } = string.Empty; - - /// - /// 证照编号。 - /// - public string? DocumentNumber { get; init; } - - /// - /// 签发日期。 - /// - public DateOnly? IssuedAt { get; init; } - - /// - /// 到期日期。 - /// - public DateOnly? ExpiresAt { get; init; } - - /// - /// 排序值。 - /// - public int SortOrder { get; init; } = 100; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreStaffCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreStaffCommand.cs deleted file mode 100644 index 26dce0d..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreStaffCommand.cs +++ /dev/null @@ -1,36 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Merchants.Enums; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 创建门店员工命令。 -/// -public sealed record CreateStoreStaffCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 姓名。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 手机号。 - /// - public string Phone { get; init; } = string.Empty; - - /// - /// 邮箱。 - /// - public string? Email { get; init; } - - /// - /// 角色。 - /// - public StaffRoleType RoleType { get; init; } = StaffRoleType.FrontDesk; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreTableAreaCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreTableAreaCommand.cs deleted file mode 100644 index 60511b4..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/CreateStoreTableAreaCommand.cs +++ /dev/null @@ -1,30 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 创建桌台区域命令。 -/// -public sealed record CreateStoreTableAreaCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 区域名称。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 区域描述。 - /// - public string? Description { get; init; } - - /// - /// 排序值。 - /// - public int SortOrder { get; init; } = 100; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreBusinessHourCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreBusinessHourCommand.cs deleted file mode 100644 index d101680..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreBusinessHourCommand.cs +++ /dev/null @@ -1,19 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 删除营业时段命令。 -/// -public sealed record DeleteStoreBusinessHourCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 营业时段 ID。 - /// - public long BusinessHourId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreCommand.cs deleted file mode 100644 index 9a66dbb..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreCommand.cs +++ /dev/null @@ -1,14 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 删除门店命令。 -/// -public sealed class DeleteStoreCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; set; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreDeliveryZoneCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreDeliveryZoneCommand.cs deleted file mode 100644 index 0e9e57d..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreDeliveryZoneCommand.cs +++ /dev/null @@ -1,19 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 删除配送区域命令。 -/// -public sealed record DeleteStoreDeliveryZoneCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 配送区域 ID。 - /// - public long DeliveryZoneId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreEmployeeShiftCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreEmployeeShiftCommand.cs deleted file mode 100644 index 0e75d12..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreEmployeeShiftCommand.cs +++ /dev/null @@ -1,19 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 删除员工排班命令。 -/// -public sealed record DeleteStoreEmployeeShiftCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 排班 ID。 - /// - public long ShiftId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreHolidayCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreHolidayCommand.cs deleted file mode 100644 index 8e86eb8..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreHolidayCommand.cs +++ /dev/null @@ -1,19 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 删除节假日配置命令。 -/// -public sealed record DeleteStoreHolidayCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 节假日 ID。 - /// - public long HolidayId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStorePickupSlotCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStorePickupSlotCommand.cs deleted file mode 100644 index e1a80f5..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStorePickupSlotCommand.cs +++ /dev/null @@ -1,19 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 删除自提档期命令。 -/// -public sealed record DeleteStorePickupSlotCommand : IRequest -{ - /// - /// 档期 ID。 - /// - public long SlotId { get; init; } - - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreQualificationCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreQualificationCommand.cs deleted file mode 100644 index 59e954c..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreQualificationCommand.cs +++ /dev/null @@ -1,19 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 删除门店资质命令。 -/// -public sealed record DeleteStoreQualificationCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 资质 ID。 - /// - public long QualificationId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreStaffCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreStaffCommand.cs deleted file mode 100644 index 6c9c94b..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreStaffCommand.cs +++ /dev/null @@ -1,19 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 删除门店员工命令。 -/// -public sealed record DeleteStoreStaffCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 员工 ID。 - /// - public long StaffId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreTableAreaCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreTableAreaCommand.cs deleted file mode 100644 index 9f74c48..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreTableAreaCommand.cs +++ /dev/null @@ -1,19 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 删除桌台区域命令。 -/// -public sealed record DeleteStoreTableAreaCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 区域 ID。 - /// - public long AreaId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreTableCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreTableCommand.cs deleted file mode 100644 index 0480296..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/DeleteStoreTableCommand.cs +++ /dev/null @@ -1,19 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 删除桌码命令。 -/// -public sealed record DeleteStoreTableCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 桌台 ID。 - /// - public long TableId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/GenerateStoreTablesCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/GenerateStoreTablesCommand.cs deleted file mode 100644 index 4c10d56..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/GenerateStoreTablesCommand.cs +++ /dev/null @@ -1,45 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 批量生成桌码命令。 -/// -public sealed record GenerateStoreTablesCommand : IRequest> -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 桌码前缀。 - /// - public string TableCodePrefix { get; init; } = "T"; - - /// - /// 起始序号。 - /// - public int StartNumber { get; init; } = 1; - - /// - /// 生成数量。 - /// - public int Count { get; init; } - - /// - /// 默认容量。 - /// - public int DefaultCapacity { get; init; } = 2; - - /// - /// 区域 ID。 - /// - public long? AreaId { get; init; } - - /// - /// 标签。 - /// - public string? Tags { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/SubmitStoreAuditCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/SubmitStoreAuditCommand.cs deleted file mode 100644 index 3e9802b..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/SubmitStoreAuditCommand.cs +++ /dev/null @@ -1,14 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 提交门店审核命令。 -/// -public sealed record SubmitStoreAuditCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/ToggleBusinessStatusCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/ToggleBusinessStatusCommand.cs deleted file mode 100644 index 000f677..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/ToggleBusinessStatusCommand.cs +++ /dev/null @@ -1,31 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Enums; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 切换门店经营状态命令。 -/// -public sealed record ToggleBusinessStatusCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 目标经营状态。 - /// - public StoreBusinessStatus BusinessStatus { get; init; } - - /// - /// 歇业原因。 - /// - public StoreClosureReason? ClosureReason { get; init; } - - /// - /// 歇业原因补充说明。 - /// - public string? ClosureReasonText { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreBusinessHourCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreBusinessHourCommand.cs deleted file mode 100644 index 7c13e2e..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreBusinessHourCommand.cs +++ /dev/null @@ -1,51 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Enums; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 更新营业时段命令。 -/// -public sealed record UpdateStoreBusinessHourCommand : IRequest -{ - /// - /// 营业时段 ID。 - /// - public long BusinessHourId { get; init; } - - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 星期几。 - /// - public DayOfWeek DayOfWeek { get; init; } - - /// - /// 时段类型。 - /// - public BusinessHourType HourType { get; init; } = BusinessHourType.Normal; - - /// - /// 开始时间。 - /// - public TimeSpan StartTime { get; init; } - - /// - /// 结束时间。 - /// - public TimeSpan EndTime { get; init; } - - /// - /// 容量限制。 - /// - public int? CapacityLimit { get; init; } - - /// - /// 备注。 - /// - public string? Notes { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreCommand.cs deleted file mode 100644 index 3d91b4a..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreCommand.cs +++ /dev/null @@ -1,126 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Enums; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 更新门店命令。 -/// -public sealed record UpdateStoreCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 商户 ID。 - /// - public long MerchantId { get; init; } - - /// - /// 门店编码。 - /// - public string Code { get; init; } = string.Empty; - - /// - /// 门店名称。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 电话。 - /// - public string? Phone { get; init; } - - /// - /// 负责人。 - /// - public string? ManagerName { get; init; } - - /// - /// 状态。 - /// - public StoreStatus Status { get; init; } = StoreStatus.Closed; - - /// - /// 门头招牌图。 - /// - public string? SignboardImageUrl { get; init; } - - /// - /// 行业类目 ID。 - /// - public long? CategoryId { get; init; } - - /// - /// 省份。 - /// - public string? Province { get; init; } - - /// - /// 城市。 - /// - public string? City { get; init; } - - /// - /// 区县。 - /// - public string? District { get; init; } - - /// - /// 详细地址。 - /// - public string? Address { get; init; } - - /// - /// 经度。 - /// - public double? Longitude { get; init; } - - /// - /// 纬度。 - /// - public double? Latitude { get; init; } - - /// - /// 公告。 - /// - public string? Announcement { get; init; } - - /// - /// 标签。 - /// - public string? Tags { get; init; } - - /// - /// 配送半径。 - /// - public decimal DeliveryRadiusKm { get; init; } - - /// - /// 支持堂食。 - /// - public bool SupportsDineIn { get; init; } = true; - - /// - /// 支持自提。 - /// - public bool SupportsPickup { get; init; } = true; - - /// - /// 支持配送。 - /// - public bool SupportsDelivery { get; init; } = true; - - /// - /// 支持预约。 - /// - public bool SupportsReservation { get; init; } - - /// - /// 支持排队叫号。 - /// - public bool SupportsQueueing { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreDeliveryZoneCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreDeliveryZoneCommand.cs deleted file mode 100644 index e21ded5..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreDeliveryZoneCommand.cs +++ /dev/null @@ -1,50 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 更新配送区域命令。 -/// -public sealed record UpdateStoreDeliveryZoneCommand : IRequest -{ - /// - /// 配送区域 ID。 - /// - public long DeliveryZoneId { get; init; } - - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 区域名称。 - /// - public string ZoneName { get; init; } = string.Empty; - - /// - /// GeoJSON。 - /// - public string PolygonGeoJson { get; init; } = string.Empty; - - /// - /// 起送价。 - /// - public decimal? MinimumOrderAmount { get; init; } - - /// - /// 配送费。 - /// - public decimal? DeliveryFee { get; init; } - - /// - /// 预计分钟。 - /// - public int? EstimatedMinutes { get; init; } - - /// - /// 排序。 - /// - public int SortOrder { get; init; } = 100; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreEmployeeShiftCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreEmployeeShiftCommand.cs deleted file mode 100644 index c1da376..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreEmployeeShiftCommand.cs +++ /dev/null @@ -1,51 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Merchants.Enums; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 更新员工排班命令。 -/// -public sealed record UpdateStoreEmployeeShiftCommand : IRequest -{ - /// - /// 排班 ID。 - /// - public long ShiftId { get; init; } - - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 员工 ID。 - /// - public long StaffId { get; init; } - - /// - /// 班次日期。 - /// - public DateTime ShiftDate { get; init; } - - /// - /// 开始时间。 - /// - public TimeSpan StartTime { get; init; } - - /// - /// 结束时间。 - /// - public TimeSpan EndTime { get; init; } - - /// - /// 排班角色。 - /// - public StaffRoleType RoleType { get; init; } = StaffRoleType.FrontDesk; - - /// - /// 备注。 - /// - public string? Notes { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreFeeCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreFeeCommand.cs deleted file mode 100644 index 8a64005..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreFeeCommand.cs +++ /dev/null @@ -1,51 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Enums; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 更新门店费用配置命令。 -/// -public sealed record UpdateStoreFeeCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 起送费。 - /// - public decimal MinimumOrderAmount { get; init; } - - /// - /// 配送费。 - /// - public decimal DeliveryFee { get; init; } - - /// - /// 打包费模式。 - /// - public PackagingFeeMode PackagingFeeMode { get; init; } - - /// - /// 订单打包费规则。 - /// - public OrderPackagingFeeMode OrderPackagingFeeMode { get; init; } = OrderPackagingFeeMode.Fixed; - - /// - /// 固定打包费。 - /// - public decimal? FixedPackagingFee { get; init; } - - /// - /// 阶梯打包费配置。 - /// - public IReadOnlyList PackagingFeeTiers { get; init; } = []; - - /// - /// 免配送费门槛。 - /// - public decimal? FreeDeliveryThreshold { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreHolidayCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreHolidayCommand.cs deleted file mode 100644 index 4552a67..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreHolidayCommand.cs +++ /dev/null @@ -1,56 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Enums; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 更新临时时段配置命令。 -/// -public sealed record UpdateStoreHolidayCommand : IRequest -{ - /// - /// 节假日 ID。 - /// - public long HolidayId { get; init; } - - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 开始日期。 - /// - public DateTime Date { get; init; } - - /// - /// 结束日期(可选)。 - /// - public DateTime? EndDate { get; init; } - - /// - /// 是否全天。 - /// - public bool IsAllDay { get; init; } = true; - - /// - /// 开始时间(IsAllDay=false 时必填)。 - /// - public TimeSpan? StartTime { get; init; } - - /// - /// 结束时间(IsAllDay=false 时必填)。 - /// - public TimeSpan? EndTime { get; init; } - - /// - /// 覆盖类型。 - /// - public OverrideType OverrideType { get; init; } = OverrideType.Closed; - - /// - /// 说明。 - /// - public string? Reason { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStorePickupSlotCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStorePickupSlotCommand.cs deleted file mode 100644 index 9505407..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStorePickupSlotCommand.cs +++ /dev/null @@ -1,55 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 更新自提档期命令。 -/// -public sealed record UpdateStorePickupSlotCommand : IRequest -{ - /// - /// 档期 ID。 - /// - public long SlotId { get; init; } - - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 名称。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 开始时间。 - /// - public TimeSpan StartTime { get; init; } - - /// - /// 结束时间。 - /// - public TimeSpan EndTime { get; init; } - - /// - /// 截单分钟。 - /// - public int CutoffMinutes { get; init; } - - /// - /// 容量。 - /// - public int Capacity { get; init; } - - /// - /// 适用星期。 - /// - public string Weekdays { get; init; } = string.Empty; - - /// - /// 是否启用。 - /// - public bool IsEnabled { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreQualificationCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreQualificationCommand.cs deleted file mode 100644 index 4bcda24..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreQualificationCommand.cs +++ /dev/null @@ -1,45 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 更新门店资质命令。 -/// -public sealed record UpdateStoreQualificationCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 资质 ID。 - /// - public long QualificationId { get; init; } - - /// - /// 证照文件 URL。 - /// - public string? FileUrl { get; init; } - - /// - /// 证照编号。 - /// - public string? DocumentNumber { get; init; } - - /// - /// 签发日期。 - /// - public DateOnly? IssuedAt { get; init; } - - /// - /// 到期日期。 - /// - public DateOnly? ExpiresAt { get; init; } - - /// - /// 排序值。 - /// - public int? SortOrder { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreStaffCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreStaffCommand.cs deleted file mode 100644 index 335a9cf..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreStaffCommand.cs +++ /dev/null @@ -1,46 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Merchants.Enums; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 更新门店员工命令。 -/// -public sealed record UpdateStoreStaffCommand : IRequest -{ - /// - /// 员工 ID。 - /// - public long StaffId { get; init; } - - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 姓名。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 手机号。 - /// - public string Phone { get; init; } = string.Empty; - - /// - /// 邮箱。 - /// - public string? Email { get; init; } - - /// - /// 角色。 - /// - public StaffRoleType RoleType { get; init; } = StaffRoleType.FrontDesk; - - /// - /// 状态。 - /// - public StaffStatus Status { get; init; } = StaffStatus.Active; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreTableAreaCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreTableAreaCommand.cs deleted file mode 100644 index b113491..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreTableAreaCommand.cs +++ /dev/null @@ -1,35 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 更新桌台区域命令。 -/// -public sealed record UpdateStoreTableAreaCommand : IRequest -{ - /// - /// 区域 ID。 - /// - public long AreaId { get; init; } - - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 区域名称。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 区域描述。 - /// - public string? Description { get; init; } - - /// - /// 排序值。 - /// - public int SortOrder { get; init; } = 100; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreTableCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreTableCommand.cs deleted file mode 100644 index d93e92c..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpdateStoreTableCommand.cs +++ /dev/null @@ -1,46 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Enums; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 更新桌码命令。 -/// -public sealed record UpdateStoreTableCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 桌台 ID。 - /// - public long TableId { get; init; } - - /// - /// 区域 ID。 - /// - public long? AreaId { get; init; } - - /// - /// 桌码。 - /// - public string TableCode { get; init; } = string.Empty; - - /// - /// 容量。 - /// - public int Capacity { get; init; } - - /// - /// 标签。 - /// - public string? Tags { get; init; } - - /// - /// 状态。 - /// - public StoreTableStatus Status { get; init; } = StoreTableStatus.Idle; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpsertStorePickupSettingCommand.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpsertStorePickupSettingCommand.cs deleted file mode 100644 index 4822b8f..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Commands/UpsertStorePickupSettingCommand.cs +++ /dev/null @@ -1,35 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; - -namespace TakeoutSaaS.Application.App.Stores.Commands; - -/// -/// 新增或更新自提配置命令。 -/// -public sealed record UpsertStorePickupSettingCommand : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 是否允许当天。 - /// - public bool AllowToday { get; init; } = true; - - /// - /// 可预约天数。 - /// - public int AllowDaysAhead { get; init; } = 3; - - /// - /// 默认截单分钟。 - /// - public int DefaultCutoffMinutes { get; init; } = 30; - - /// - /// 单笔最大份数。 - /// - public int? MaxQuantityPerOrder { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/BatchUpdateBusinessHoursCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/BatchUpdateBusinessHoursCommandHandler.cs deleted file mode 100644 index af80664..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/BatchUpdateBusinessHoursCommandHandler.cs +++ /dev/null @@ -1,75 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Application.App.Stores.Validators; -using TakeoutSaaS.Domain.Stores.Entities; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 批量更新营业时段处理器。 -/// -public sealed class BatchUpdateBusinessHoursCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler> -{ - /// - public async Task> Handle(BatchUpdateBusinessHoursCommand request, CancellationToken cancellationToken) - { - // 1. 校验门店存在 - var tenantId = tenantProvider.GetCurrentTenantId(); - var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken); - if (store is null) - { - throw new BusinessException(ErrorCodes.NotFound, "门店不存在"); - } - var storeTenantId = store.TenantId; - - // 2. (空行后) 校验时段重叠 - var overlapError = BusinessHourValidators.ValidateOverlap(request.Items); - if (!string.IsNullOrWhiteSpace(overlapError)) - { - throw new BusinessException(ErrorCodes.ValidationFailed, overlapError); - } - - // 3. (空行后) 删除旧时段 - var existingHours = await storeRepository.GetBusinessHoursAsync(request.StoreId, storeTenantId, cancellationToken); - foreach (var hour in existingHours) - { - await storeRepository.DeleteBusinessHourAsync(hour.Id, storeTenantId, cancellationToken); - } - - // 4. (空行后) 新增时段配置 - if (request.Items.Count > 0) - { - var hours = request.Items.Select(item => new StoreBusinessHour - { - TenantId = storeTenantId, - StoreId = request.StoreId, - DayOfWeek = item.DayOfWeek, - HourType = item.HourType, - StartTime = item.StartTime, - EndTime = item.EndTime, - CapacityLimit = item.CapacityLimit, - Notes = item.Notes?.Trim() - }).ToList(); - - await storeRepository.AddBusinessHoursAsync(hours, cancellationToken); - } - - // 5. (空行后) 保存并返回结果 - await storeRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("批量更新门店营业时段 {StoreId}", request.StoreId); - - var refreshed = await storeRepository.GetBusinessHoursAsync(request.StoreId, storeTenantId, cancellationToken); - return refreshed.Select(StoreMapping.ToDto).ToList(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CalculateStoreFeeQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CalculateStoreFeeQueryHandler.cs deleted file mode 100644 index c45603b..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CalculateStoreFeeQueryHandler.cs +++ /dev/null @@ -1,55 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Application.App.Stores.Queries; -using TakeoutSaaS.Application.App.Stores.Services; -using TakeoutSaaS.Domain.Stores.Entities; -using TakeoutSaaS.Domain.Stores.Enums; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 门店费用预览查询处理器。 -/// -public sealed class CalculateStoreFeeQueryHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - IStoreFeeCalculationService feeCalculationService) - : IRequestHandler -{ - /// - public async Task Handle(CalculateStoreFeeQuery request, CancellationToken cancellationToken) - { - // 1. 校验门店存在 - var tenantId = tenantProvider.GetCurrentTenantId(); - var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken); - if (store is null) - { - throw new BusinessException(ErrorCodes.NotFound, "门店不存在"); - } - - // 2. (空行后) 获取费用配置 - var fee = await storeRepository.GetStoreFeeAsync(request.StoreId, tenantId, cancellationToken) - ?? new StoreFee - { - StoreId = request.StoreId, - MinimumOrderAmount = 0m, - BaseDeliveryFee = 0m, - PackagingFeeMode = PackagingFeeMode.Fixed, - OrderPackagingFeeMode = OrderPackagingFeeMode.Fixed, - FixedPackagingFee = 0m - }; - - // 3. (空行后) 执行费用计算 - var calculationRequest = new StoreFeeCalculationRequestDto - { - OrderAmount = request.OrderAmount, - ItemCount = request.ItemCount, - Items = request.Items - }; - return feeCalculationService.Calculate(fee, calculationRequest); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CheckStoreDeliveryZoneQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CheckStoreDeliveryZoneQueryHandler.cs deleted file mode 100644 index be01143..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CheckStoreDeliveryZoneQueryHandler.cs +++ /dev/null @@ -1,60 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Application.App.Stores.Queries; -using TakeoutSaaS.Application.App.Stores.Services; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 配送范围检测查询处理器。 -/// -public sealed class CheckStoreDeliveryZoneQueryHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - IDeliveryZoneService deliveryZoneService) - : IRequestHandler -{ - /// - public async Task Handle(CheckStoreDeliveryZoneQuery request, CancellationToken cancellationToken) - { - // 1. 校验门店存在 - var tenantId = tenantProvider.GetCurrentTenantId(); - var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken); - if (store is null) - { - throw new BusinessException(ErrorCodes.NotFound, "门店不存在"); - } - - // 2. (空行后) 执行配送范围判断 - var zones = await storeRepository.GetDeliveryZonesAsync(request.StoreId, tenantId, cancellationToken); - var result = deliveryZoneService.CheckPointInZones(zones, request.Longitude, request.Latitude); - - // 3. (空行后) 计算距离 - if (store.Longitude.HasValue && store.Latitude.HasValue) - { - var distance = CalculateDistanceKm(store.Latitude.Value, store.Longitude.Value, request.Latitude, request.Longitude); - result = result with { Distance = (decimal)Math.Round(distance, 2, MidpointRounding.AwayFromZero) }; - } - return result; - } - - private static double CalculateDistanceKm(double latitude1, double longitude1, double latitude2, double longitude2) - { - const double earthRadius = 6371000d; - var latRad1 = DegreesToRadians(latitude1); - var latRad2 = DegreesToRadians(latitude2); - var deltaLat = DegreesToRadians(latitude2 - latitude1); - var deltaLon = DegreesToRadians(longitude2 - longitude1); - var sinLat = Math.Sin(deltaLat / 2); - var sinLon = Math.Sin(deltaLon / 2); - var a = sinLat * sinLat + Math.Cos(latRad1) * Math.Cos(latRad2) * sinLon * sinLon; - var c = 2 * Math.Asin(Math.Min(1, Math.Sqrt(a))); - return earthRadius * c / 1000d; - } - - private static double DegreesToRadians(double degrees) => degrees * (Math.PI / 180d); -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CheckStoreQualificationsQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CheckStoreQualificationsQueryHandler.cs deleted file mode 100644 index 11dad7b..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CheckStoreQualificationsQueryHandler.cs +++ /dev/null @@ -1,133 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Application.App.Stores.Queries; -using TakeoutSaaS.Domain.Stores.Enums; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 门店资质完整性检查处理器。 -/// -public sealed class CheckStoreQualificationsQueryHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - public async Task Handle(CheckStoreQualificationsQuery request, CancellationToken cancellationToken) - { - // 1. 校验门店存在 - var tenantId = tenantProvider.GetCurrentTenantId(); - var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken); - if (store is null) - { - throw new BusinessException(ErrorCodes.NotFound, "门店不存在"); - } - - // 2. (空行后) 同主体门店默认视为完整 - if (store.OwnershipType == StoreOwnershipType.SameEntity) - { - return new StoreQualificationCheckResultDto - { - IsComplete = true, - CanSubmitAudit = true - }; - } - - // 3. (空行后) 读取资质列表并统计 - var qualifications = await storeRepository.GetQualificationsAsync(request.StoreId, tenantId, cancellationToken); - var grouped = qualifications - .GroupBy(x => x.QualificationType) - .ToDictionary(x => x.Key, x => x.ToList()); - - var expiredCount = qualifications.Count(x => x.IsExpired); - var expiringSoonCount = qualifications.Count(x => x.IsExpiringSoon); - - var foodStats = BuildRequirement(grouped, StoreQualificationType.FoodServiceLicense, true); - var businessStats = BuildRequirement(grouped, StoreQualificationType.BusinessLicense, true); - var storefrontStats = BuildRequirement(grouped, StoreQualificationType.StorefrontPhoto, true); - var interiorStats = BuildInteriorRequirement(grouped); - - var hasLicense = foodStats.IsValid || businessStats.IsValid; - var hasStorefront = storefrontStats.IsValid; - var hasInterior = interiorStats.IsValid; - - var missingTypes = new List(); - if (!hasLicense) - { - missingTypes.Add("营业执照/食品经营许可证"); - } - - if (!hasStorefront) - { - missingTypes.Add("门头实景照"); - } - - if (!hasInterior) - { - missingTypes.Add("店内环境照(至少2张)"); - } - - var warnings = missingTypes.Count == 0 - ? Array.Empty() - : missingTypes.Select(type => $"缺少必要资质:{type}").ToArray(); - - // 4. (空行后) 组装结果 - var requirements = new List - { - foodStats, - businessStats, - storefrontStats, - interiorStats - }; - - var isComplete = hasLicense && hasStorefront && hasInterior; - return new StoreQualificationCheckResultDto - { - IsComplete = isComplete, - CanSubmitAudit = isComplete, - RequiredTypes = requirements, - ExpiringSoonCount = expiringSoonCount, - ExpiredCount = expiredCount, - MissingTypes = missingTypes, - Warnings = warnings - }; - } - - private static StoreQualificationRequirementDto BuildRequirement( - IReadOnlyDictionary> grouped, - StoreQualificationType type, - bool required) - { - var list = grouped.TryGetValue(type, out var items) ? items : []; - var hasUploaded = list.Count > 0; - var hasValid = list.Any(item => !item.IsExpired); - return new StoreQualificationRequirementDto - { - QualificationType = type, - IsRequired = required, - IsUploaded = hasUploaded, - IsValid = hasValid, - UploadedCount = list.Count - }; - } - - private static StoreQualificationRequirementDto BuildInteriorRequirement( - IReadOnlyDictionary> grouped) - { - var list = grouped.TryGetValue(StoreQualificationType.InteriorPhoto, out var items) ? items : []; - var validCount = list.Count(item => !item.IsExpired); - return new StoreQualificationRequirementDto - { - QualificationType = StoreQualificationType.InteriorPhoto, - IsRequired = true, - IsUploaded = list.Count > 0, - IsValid = validCount >= 2, - UploadedCount = list.Count - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreBusinessHourCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreBusinessHourCommandHandler.cs deleted file mode 100644 index 9b474b3..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreBusinessHourCommandHandler.cs +++ /dev/null @@ -1,57 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Entities; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 创建营业时段处理器。 -/// -public sealed class CreateStoreBusinessHourCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - private readonly IStoreRepository _storeRepository = storeRepository; - private readonly ITenantProvider _tenantProvider = tenantProvider; - private readonly ILogger _logger = logger; - - /// - public async Task Handle(CreateStoreBusinessHourCommand request, CancellationToken cancellationToken) - { - // 1. 校验门店存在 - var tenantId = _tenantProvider.GetCurrentTenantId(); - var store = await _storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken); - if (store is null) - { - throw new BusinessException(ErrorCodes.NotFound, "门店不存在"); - } - - // 2. 构建实体 - var hour = new StoreBusinessHour - { - StoreId = request.StoreId, - DayOfWeek = request.DayOfWeek, - HourType = request.HourType, - StartTime = request.StartTime, - EndTime = request.EndTime, - CapacityLimit = request.CapacityLimit, - Notes = request.Notes?.Trim() - }; - - // 3. 持久化 - await _storeRepository.AddBusinessHoursAsync(new[] { hour }, cancellationToken); - await _storeRepository.SaveChangesAsync(cancellationToken); - _logger.LogInformation("创建营业时段 {BusinessHourId} 对应门店 {StoreId}", hour.Id, request.StoreId); - - // 4. 返回 DTO - return StoreMapping.ToDto(hour); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreCommandHandler.cs deleted file mode 100644 index 29dd965..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreCommandHandler.cs +++ /dev/null @@ -1,114 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Domain.Stores.Entities; -using TakeoutSaaS.Domain.Stores.Enums; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 创建门店命令处理器。 -/// -public sealed class CreateStoreCommandHandler( - IStoreRepository storeRepository, - IMerchantRepository merchantRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(CreateStoreCommand request, CancellationToken cancellationToken) - { - // 1. 校验商户存在并解析租户 - var currentTenantId = tenantProvider.GetCurrentTenantId(); - var merchant = await merchantRepository.FindByIdAsync(request.MerchantId, currentTenantId, cancellationToken); - if (merchant == null) - { - throw new BusinessException(ErrorCodes.NotFound, "商户不存在"); - } - var tenantId = merchant.TenantId; - - // 2. (空行后) 校验门店坐标唯一性(100 米内禁止重复) - if (request.Longitude.HasValue && request.Latitude.HasValue) - { - var isDuplicate = await storeRepository.ExistsStoreWithinDistanceAsync( - request.MerchantId, - tenantId, - request.Longitude.Value, - request.Latitude.Value, - 100, - cancellationToken); - if (isDuplicate) - { - throw new BusinessException(ErrorCodes.Conflict, "该位置已存在门店"); - } - } - - // 3. (空行后) 计算审核与经营状态 - var now = DateTime.UtcNow; - var isSameEntity = request.OwnershipType == StoreOwnershipType.SameEntity; - var auditStatus = isSameEntity ? StoreAuditStatus.Activated : StoreAuditStatus.Draft; - var businessStatus = StoreBusinessStatus.Resting; - DateTime? activatedAt = isSameEntity ? now : null; - - // 4. (空行后) 构建实体 - var store = new Store - { - TenantId = tenantId, - MerchantId = request.MerchantId, - Code = request.Code.Trim(), - Name = request.Name.Trim(), - Phone = request.Phone?.Trim(), - ManagerName = request.ManagerName?.Trim(), - Status = request.Status, - SignboardImageUrl = request.SignboardImageUrl?.Trim(), - OwnershipType = request.OwnershipType, - AuditStatus = auditStatus, - BusinessStatus = businessStatus, - CategoryId = request.CategoryId, - ActivatedAt = activatedAt, - Province = request.Province?.Trim(), - City = request.City?.Trim(), - District = request.District?.Trim(), - Address = request.Address?.Trim(), - Longitude = request.Longitude, - Latitude = request.Latitude, - Announcement = request.Announcement?.Trim(), - Tags = request.Tags?.Trim(), - DeliveryRadiusKm = request.DeliveryRadiusKm, - SupportsDineIn = request.SupportsDineIn, - SupportsPickup = request.SupportsPickup, - SupportsDelivery = request.SupportsDelivery, - SupportsReservation = request.SupportsReservation, - SupportsQueueing = request.SupportsQueueing - }; - - // 5. (空行后) 持久化门店以获取标识 - await storeRepository.AddStoreAsync(store, cancellationToken); - await storeRepository.SaveChangesAsync(cancellationToken); - - // 6. (空行后) 初始化费用配置 - await storeRepository.AddStoreFeeAsync(new StoreFee - { - TenantId = tenantId, - StoreId = store.Id, - MinimumOrderAmount = 0m, - BaseDeliveryFee = 0m, - PackagingFeeMode = PackagingFeeMode.Fixed, - OrderPackagingFeeMode = OrderPackagingFeeMode.Fixed, - FixedPackagingFee = 0m - }, cancellationToken); - await storeRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("创建门店 {StoreId} - {StoreName}", store.Id, store.Name); - - // 7. (空行后) 返回 DTO - return StoreMapping.ToDto(store); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreDeliveryZoneCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreDeliveryZoneCommandHandler.cs deleted file mode 100644 index db6a1b7..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreDeliveryZoneCommandHandler.cs +++ /dev/null @@ -1,65 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Application.App.Stores.Services; -using TakeoutSaaS.Domain.Stores.Entities; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 创建配送区域处理器。 -/// -public sealed class CreateStoreDeliveryZoneCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - IGeoJsonValidationService geoJsonValidationService, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(CreateStoreDeliveryZoneCommand request, CancellationToken cancellationToken) - { - // 1. 校验门店存在 - var tenantId = tenantProvider.GetCurrentTenantId(); - var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken); - if (store is null) - { - throw new BusinessException(ErrorCodes.NotFound, "门店不存在"); - } - var storeTenantId = store.TenantId; - - // 2. (空行后) 校验 GeoJSON - var validation = geoJsonValidationService.ValidatePolygon(request.PolygonGeoJson); - if (!validation.IsValid) - { - throw new BusinessException(ErrorCodes.ValidationFailed, validation.ErrorMessage ?? "配送范围格式错误"); - } - - // 3. (空行后) 构建实体 - var zone = new StoreDeliveryZone - { - TenantId = storeTenantId, - StoreId = request.StoreId, - ZoneName = request.ZoneName.Trim(), - PolygonGeoJson = (validation.NormalizedGeoJson ?? request.PolygonGeoJson).Trim(), - MinimumOrderAmount = request.MinimumOrderAmount, - DeliveryFee = request.DeliveryFee, - EstimatedMinutes = request.EstimatedMinutes, - SortOrder = request.SortOrder - }; - - // 4. (空行后) 持久化 - await storeRepository.AddDeliveryZonesAsync(new[] { zone }, cancellationToken); - await storeRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("创建配送区域 {DeliveryZoneId} 对应门店 {StoreId}", zone.Id, request.StoreId); - - // 5. (空行后) 返回 DTO - return StoreMapping.ToDto(zone); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreEmployeeShiftCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreEmployeeShiftCommandHandler.cs deleted file mode 100644 index b47af84..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreEmployeeShiftCommandHandler.cs +++ /dev/null @@ -1,72 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Domain.Stores.Entities; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 创建排班处理器。 -/// -public sealed class CreateStoreEmployeeShiftCommandHandler( - IStoreRepository storeRepository, - IMerchantRepository merchantRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(CreateStoreEmployeeShiftCommand request, CancellationToken cancellationToken) - { - // 1. 校验门店存在 - var tenantId = tenantProvider.GetCurrentTenantId(); - var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken); - if (store is null) - { - throw new BusinessException(ErrorCodes.NotFound, "门店不存在"); - } - - // 2. 校验员工归属与状态 - var staff = await merchantRepository.FindStaffByIdAsync(request.StaffId, tenantId, cancellationToken); - if (staff is null || (staff.StoreId.HasValue && staff.StoreId != request.StoreId)) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "员工不存在或不属于该门店"); - } - - // 3. 校验日期与冲突 - var from = request.ShiftDate.Date; - var to = request.ShiftDate.Date; - var shifts = await storeRepository.GetShiftsAsync(request.StoreId, tenantId, from, to, cancellationToken); - var hasConflict = shifts.Any(x => x.StaffId == request.StaffId && x.ShiftDate == request.ShiftDate); - if (hasConflict) - { - throw new BusinessException(ErrorCodes.Conflict, "该员工当日已存在排班"); - } - - // 4. 构建实体 - var shift = new StoreEmployeeShift - { - StoreId = request.StoreId, - StaffId = request.StaffId, - ShiftDate = request.ShiftDate.Date, - StartTime = request.StartTime, - EndTime = request.EndTime, - RoleType = request.RoleType, - Notes = request.Notes?.Trim() - }; - - // 5. 持久化 - await storeRepository.AddShiftsAsync(new[] { shift }, cancellationToken); - await storeRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("创建排班 {ShiftId} 员工 {StaffId} 门店 {StoreId}", shift.Id, shift.StaffId, shift.StoreId); - - // 6. 返回 DTO - return StoreMapping.ToDto(shift); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreHolidayCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreHolidayCommandHandler.cs deleted file mode 100644 index a3088ce..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreHolidayCommandHandler.cs +++ /dev/null @@ -1,73 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Entities; -using TakeoutSaaS.Domain.Stores.Enums; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 创建节假日配置处理器。 -/// -public sealed class CreateStoreHolidayCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - private readonly IStoreRepository _storeRepository = storeRepository; - private readonly ITenantProvider _tenantProvider = tenantProvider; - private readonly ILogger _logger = logger; - - /// - public async Task Handle(CreateStoreHolidayCommand request, CancellationToken cancellationToken) - { - // 1. 校验门店存在 - var tenantId = _tenantProvider.GetCurrentTenantId(); - var store = await _storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken); - if (store is null) - { - throw new BusinessException(ErrorCodes.NotFound, "门店不存在"); - } - var storeTenantId = store.TenantId; - - // 2. 构建实体 - var holiday = new StoreHoliday - { - TenantId = storeTenantId, - StoreId = request.StoreId, - Date = NormalizeToUtc(request.Date), - EndDate = request.EndDate.HasValue ? NormalizeToUtc(request.EndDate.Value) : null, - IsAllDay = request.IsAllDay, - StartTime = request.StartTime, - EndTime = request.EndTime, - OverrideType = request.OverrideType, - IsClosed = request.OverrideType == OverrideType.Closed, - Reason = request.Reason?.Trim() - }; - - // 3. 持久化 - await _storeRepository.AddHolidaysAsync(new[] { holiday }, cancellationToken); - await _storeRepository.SaveChangesAsync(cancellationToken); - _logger.LogInformation("创建节假日 {HolidayId} 对应门店 {StoreId}", holiday.Id, request.StoreId); - - // 4. 返回 DTO - return StoreMapping.ToDto(holiday); - } - - private static DateTime NormalizeToUtc(DateTime value) - { - return value.Kind switch - { - DateTimeKind.Utc => value, - DateTimeKind.Local => value.ToUniversalTime(), - _ => DateTime.SpecifyKind(value, DateTimeKind.Utc) - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStorePickupSlotCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStorePickupSlotCommandHandler.cs deleted file mode 100644 index 9454424..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStorePickupSlotCommandHandler.cs +++ /dev/null @@ -1,64 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Entities; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 创建自提档期处理器。 -/// -public sealed class CreateStorePickupSlotCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(CreateStorePickupSlotCommand request, CancellationToken cancellationToken) - { - // 1. 校验门店 - var tenantId = tenantProvider.GetCurrentTenantId(); - var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken); - if (store is null) - { - throw new BusinessException(ErrorCodes.NotFound, "门店不存在"); - } - - // 2. 新建档期 - var slot = new StorePickupSlot - { - TenantId = tenantId, - StoreId = request.StoreId, - Name = request.Name.Trim(), - StartTime = request.StartTime, - EndTime = request.EndTime, - CutoffMinutes = request.CutoffMinutes, - Capacity = request.Capacity, - ReservedCount = 0, - Weekdays = request.Weekdays, - IsEnabled = request.IsEnabled - }; - await storeRepository.AddPickupSlotsAsync(new[] { slot }, cancellationToken); - await storeRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("创建自提档期 {SlotId} for store {StoreId}", slot.Id, request.StoreId); - return new StorePickupSlotDto - { - Id = slot.Id, - StoreId = slot.StoreId, - Name = slot.Name, - StartTime = slot.StartTime, - EndTime = slot.EndTime, - CutoffMinutes = slot.CutoffMinutes, - Capacity = slot.Capacity, - ReservedCount = slot.ReservedCount, - Weekdays = slot.Weekdays, - IsEnabled = slot.IsEnabled - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreQualificationCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreQualificationCommandHandler.cs deleted file mode 100644 index 6f4ebd5..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreQualificationCommandHandler.cs +++ /dev/null @@ -1,85 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Entities; -using TakeoutSaaS.Domain.Stores.Enums; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 创建门店资质处理器。 -/// -public sealed class CreateStoreQualificationCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(CreateStoreQualificationCommand request, CancellationToken cancellationToken) - { - // 1. 校验门店存在 - var tenantId = tenantProvider.GetCurrentTenantId(); - var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken); - if (store is null) - { - throw new BusinessException(ErrorCodes.NotFound, "门店不存在"); - } - - // 2. (空行后) 审核中门店禁止修改资质 - if (store.AuditStatus == StoreAuditStatus.Pending) - { - throw new BusinessException(ErrorCodes.Conflict, "门店审核中,无法修改资质"); - } - - // 3. (空行后) 检查是否需要替换同类型记录 - var qualifications = await storeRepository.GetQualificationsAsync(request.StoreId, tenantId, cancellationToken); - var shouldReplace = ShouldReplace(request.QualificationType); - var existing = shouldReplace - ? qualifications.FirstOrDefault(x => x.QualificationType == request.QualificationType) - : null; - - // 4. (空行后) 构建或更新资质实体 - if (existing is null) - { - existing = new StoreQualification - { - StoreId = request.StoreId, - QualificationType = request.QualificationType, - FileUrl = request.FileUrl.Trim(), - DocumentNumber = request.DocumentNumber?.Trim(), - IssuedAt = request.IssuedAt, - ExpiresAt = request.ExpiresAt, - SortOrder = request.SortOrder - }; - - await storeRepository.AddQualificationAsync(existing, cancellationToken); - } - else - { - existing.FileUrl = request.FileUrl.Trim(); - existing.DocumentNumber = request.DocumentNumber?.Trim(); - existing.IssuedAt = request.IssuedAt; - existing.ExpiresAt = request.ExpiresAt; - existing.SortOrder = request.SortOrder; - - await storeRepository.UpdateQualificationAsync(existing, cancellationToken); - } - - // 5. (空行后) 保存变更并返回结果 - await storeRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("更新门店资质 {QualificationId} 对应门店 {StoreId}", existing.Id, request.StoreId); - - return StoreMapping.ToDto(existing); - } - - private static bool ShouldReplace(StoreQualificationType type) - => type is StoreQualificationType.BusinessLicense - or StoreQualificationType.FoodServiceLicense - or StoreQualificationType.StorefrontPhoto; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreStaffCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreStaffCommandHandler.cs deleted file mode 100644 index 5ae4974..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreStaffCommandHandler.cs +++ /dev/null @@ -1,56 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Merchants.Entities; -using TakeoutSaaS.Domain.Merchants.Enums; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 创建门店员工处理器。 -/// -public sealed class CreateStoreStaffCommandHandler( - IMerchantRepository merchantRepository, - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(CreateStoreStaffCommand request, CancellationToken cancellationToken) - { - // 1. 校验门店 - var tenantId = tenantProvider.GetCurrentTenantId(); - var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken); - if (store is null) - { - throw new BusinessException(ErrorCodes.NotFound, "门店不存在"); - } - - // 2. 组装员工 - var staff = new MerchantStaff - { - MerchantId = store.MerchantId, - StoreId = request.StoreId, - Name = request.Name.Trim(), - Phone = request.Phone.Trim(), - Email = request.Email?.Trim(), - RoleType = request.RoleType, - Status = StaffStatus.Active - }; - - // 3. 持久化 - await merchantRepository.AddStaffAsync(staff, cancellationToken); - await merchantRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("创建门店员工 {StaffId} 门店 {StoreId}", staff.Id, request.StoreId); - - // 4. 返回 DTO - return StoreMapping.ToDto(staff); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreTableAreaCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreTableAreaCommandHandler.cs deleted file mode 100644 index 4999f4f..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/CreateStoreTableAreaCommandHandler.cs +++ /dev/null @@ -1,58 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Entities; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 创建桌台区域处理器。 -/// -public sealed class CreateStoreTableAreaCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(CreateStoreTableAreaCommand request, CancellationToken cancellationToken) - { - // 1. 校验门店存在 - var tenantId = tenantProvider.GetCurrentTenantId(); - var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken); - if (store is null) - { - throw new BusinessException(ErrorCodes.NotFound, "门店不存在"); - } - - // 2. 校验区域名称唯一 - var existingAreas = await storeRepository.GetTableAreasAsync(request.StoreId, tenantId, cancellationToken); - var hasDuplicate = existingAreas.Any(x => x.Name.Equals(request.Name, StringComparison.OrdinalIgnoreCase)); - if (hasDuplicate) - { - throw new BusinessException(ErrorCodes.Conflict, "区域名称已存在"); - } - - // 3. 构建实体 - var area = new StoreTableArea - { - StoreId = request.StoreId, - Name = request.Name.Trim(), - Description = request.Description?.Trim(), - SortOrder = request.SortOrder - }; - - // 4. 持久化 - await storeRepository.AddTableAreasAsync(new[] { area }, cancellationToken); - await storeRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("创建桌台区域 {AreaId} 对应门店 {StoreId}", area.Id, request.StoreId); - - // 5. 返回 DTO - return StoreMapping.ToDto(area); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreBusinessHourCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreBusinessHourCommandHandler.cs deleted file mode 100644 index 816cd88..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreBusinessHourCommandHandler.cs +++ /dev/null @@ -1,46 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 删除营业时段处理器。 -/// -public sealed class DeleteStoreBusinessHourCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - private readonly IStoreRepository _storeRepository = storeRepository; - private readonly ITenantProvider _tenantProvider = tenantProvider; - private readonly ILogger _logger = logger; - - /// - public async Task Handle(DeleteStoreBusinessHourCommand request, CancellationToken cancellationToken) - { - // 1. 读取时段 - var tenantId = _tenantProvider.GetCurrentTenantId(); - var existing = await _storeRepository.FindBusinessHourByIdAsync(request.BusinessHourId, tenantId, cancellationToken); - if (existing is null) - { - return false; - } - - // 2. 校验门店归属 - if (existing.StoreId != request.StoreId) - { - return false; - } - - // 3. 删除 - await _storeRepository.DeleteBusinessHourAsync(request.BusinessHourId, tenantId, cancellationToken); - await _storeRepository.SaveChangesAsync(cancellationToken); - _logger.LogInformation("删除营业时段 {BusinessHourId} 对应门店 {StoreId}", request.BusinessHourId, request.StoreId); - - return true; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreCommandHandler.cs deleted file mode 100644 index 7e30eaf..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreCommandHandler.cs +++ /dev/null @@ -1,40 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 删除门店命令处理器。 -/// -public sealed class DeleteStoreCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - private readonly IStoreRepository _storeRepository = storeRepository; - private readonly ITenantProvider _tenantProvider = tenantProvider; - private readonly ILogger _logger = logger; - - /// - public async Task Handle(DeleteStoreCommand request, CancellationToken cancellationToken) - { - // 1. 校验存在性 - var tenantId = _tenantProvider.GetCurrentTenantId(); - var existing = await _storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken); - if (existing == null) - { - return false; - } - - // 2. 删除 - await _storeRepository.DeleteStoreAsync(request.StoreId, tenantId, cancellationToken); - await _storeRepository.SaveChangesAsync(cancellationToken); - _logger.LogInformation("删除门店 {StoreId}", request.StoreId); - - return true; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreDeliveryZoneCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreDeliveryZoneCommandHandler.cs deleted file mode 100644 index c7e7abb..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreDeliveryZoneCommandHandler.cs +++ /dev/null @@ -1,46 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 删除配送区域处理器。 -/// -public sealed class DeleteStoreDeliveryZoneCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - private readonly IStoreRepository _storeRepository = storeRepository; - private readonly ITenantProvider _tenantProvider = tenantProvider; - private readonly ILogger _logger = logger; - - /// - public async Task Handle(DeleteStoreDeliveryZoneCommand request, CancellationToken cancellationToken) - { - // 1. 读取区域 - var tenantId = _tenantProvider.GetCurrentTenantId(); - var existing = await _storeRepository.FindDeliveryZoneByIdAsync(request.DeliveryZoneId, tenantId, cancellationToken); - if (existing is null) - { - return false; - } - - // 2. 校验门店归属 - if (existing.StoreId != request.StoreId) - { - return false; - } - - // 3. 删除 - await _storeRepository.DeleteDeliveryZoneAsync(request.DeliveryZoneId, tenantId, cancellationToken); - await _storeRepository.SaveChangesAsync(cancellationToken); - _logger.LogInformation("删除配送区域 {DeliveryZoneId} 对应门店 {StoreId}", request.DeliveryZoneId, request.StoreId); - - return true; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreEmployeeShiftCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreEmployeeShiftCommandHandler.cs deleted file mode 100644 index d29a555..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreEmployeeShiftCommandHandler.cs +++ /dev/null @@ -1,36 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 删除排班处理器。 -/// -public sealed class DeleteStoreEmployeeShiftCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(DeleteStoreEmployeeShiftCommand request, CancellationToken cancellationToken) - { - // 1. 读取排班 - var tenantId = tenantProvider.GetCurrentTenantId(); - var shift = await storeRepository.FindShiftByIdAsync(request.ShiftId, tenantId, cancellationToken); - if (shift is null || shift.StoreId != request.StoreId) - { - return false; - } - - // 2. 删除 - await storeRepository.DeleteShiftAsync(request.ShiftId, tenantId, cancellationToken); - await storeRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("删除排班 {ShiftId} 门店 {StoreId}", request.ShiftId, request.StoreId); - - return true; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreHolidayCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreHolidayCommandHandler.cs deleted file mode 100644 index a262ffe..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreHolidayCommandHandler.cs +++ /dev/null @@ -1,46 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 删除节假日配置处理器。 -/// -public sealed class DeleteStoreHolidayCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - private readonly IStoreRepository _storeRepository = storeRepository; - private readonly ITenantProvider _tenantProvider = tenantProvider; - private readonly ILogger _logger = logger; - - /// - public async Task Handle(DeleteStoreHolidayCommand request, CancellationToken cancellationToken) - { - // 1. 读取配置 - var tenantId = _tenantProvider.GetCurrentTenantId(); - var existing = await _storeRepository.FindHolidayByIdAsync(request.HolidayId, tenantId, cancellationToken); - if (existing is null) - { - return false; - } - - // 2. 校验门店归属 - if (existing.StoreId != request.StoreId) - { - return false; - } - - // 3. 删除 - await _storeRepository.DeleteHolidayAsync(request.HolidayId, tenantId, cancellationToken); - await _storeRepository.SaveChangesAsync(cancellationToken); - _logger.LogInformation("删除节假日 {HolidayId} 对应门店 {StoreId}", request.HolidayId, request.StoreId); - - return true; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStorePickupSlotCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStorePickupSlotCommandHandler.cs deleted file mode 100644 index c42e4d0..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStorePickupSlotCommandHandler.cs +++ /dev/null @@ -1,28 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 删除自提档期处理器。 -/// -public sealed class DeleteStorePickupSlotCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(DeleteStorePickupSlotCommand request, CancellationToken cancellationToken) - { - // 1. 删除档期 - var tenantId = tenantProvider.GetCurrentTenantId(); - await storeRepository.DeletePickupSlotAsync(request.SlotId, tenantId, cancellationToken); - await storeRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("删除自提档期 {SlotId}", request.SlotId); - return true; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreQualificationCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreQualificationCommandHandler.cs deleted file mode 100644 index 0d3b662..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreQualificationCommandHandler.cs +++ /dev/null @@ -1,72 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Domain.Stores.Enums; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 删除门店资质处理器。 -/// -public sealed class DeleteStoreQualificationCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(DeleteStoreQualificationCommand request, CancellationToken cancellationToken) - { - // 1. 校验门店存在 - var tenantId = tenantProvider.GetCurrentTenantId(); - var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken); - if (store is null) - { - throw new BusinessException(ErrorCodes.NotFound, "门店不存在"); - } - - // 2. (空行后) 审核中门店禁止删除资质 - if (store.AuditStatus == StoreAuditStatus.Pending) - { - throw new BusinessException(ErrorCodes.Conflict, "门店审核中,无法删除资质"); - } - - // 3. (空行后) 获取资质记录 - var qualification = await storeRepository.FindQualificationByIdAsync(request.QualificationId, tenantId, cancellationToken); - if (qualification is null || qualification.StoreId != request.StoreId) - { - return false; - } - - // 4. (空行后) 已激活的外部门店必须保留必要资质 - if (store.OwnershipType == StoreOwnershipType.DifferentEntity - && store.AuditStatus == StoreAuditStatus.Activated - && IsLicenseType(qualification.QualificationType)) - { - var qualifications = await storeRepository.GetQualificationsAsync(request.StoreId, tenantId, cancellationToken); - var remainingValid = qualifications - .Where(item => IsLicenseType(item.QualificationType)) - .Where(item => item.Id != qualification.Id && !item.IsExpired) - .ToList(); - - if (remainingValid.Count == 0) - { - throw new BusinessException(ErrorCodes.Forbidden, "不能删除必要资质"); - } - } - - // 5. (空行后) 执行删除 - await storeRepository.DeleteQualificationAsync(request.QualificationId, tenantId, cancellationToken); - await storeRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("删除门店资质 {QualificationId} 对应门店 {StoreId}", qualification.Id, request.StoreId); - - return true; - } - - private static bool IsLicenseType(StoreQualificationType type) - => type is StoreQualificationType.BusinessLicense or StoreQualificationType.FoodServiceLicense; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreStaffCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreStaffCommandHandler.cs deleted file mode 100644 index 5d438f8..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreStaffCommandHandler.cs +++ /dev/null @@ -1,35 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 删除门店员工处理器。 -/// -public sealed class DeleteStoreStaffCommandHandler( - IMerchantRepository merchantRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(DeleteStoreStaffCommand request, CancellationToken cancellationToken) - { - var tenantId = tenantProvider.GetCurrentTenantId(); - var staff = await merchantRepository.FindStaffByIdAsync(request.StaffId, tenantId, cancellationToken); - if (staff is null || staff.StoreId != request.StoreId) - { - return false; - } - - // 逻辑删除未定义,直接物理删除 - await merchantRepository.DeleteStaffAsync(staff.Id, tenantId, cancellationToken); - await merchantRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("删除门店员工 {StaffId} 门店 {StoreId}", request.StaffId, request.StoreId); - - return true; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreTableAreaCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreTableAreaCommandHandler.cs deleted file mode 100644 index 48dad11..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreTableAreaCommandHandler.cs +++ /dev/null @@ -1,52 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 删除桌台区域处理器。 -/// -public sealed class DeleteStoreTableAreaCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(DeleteStoreTableAreaCommand request, CancellationToken cancellationToken) - { - // 1. 读取区域 - var tenantId = tenantProvider.GetCurrentTenantId(); - var area = await storeRepository.FindTableAreaByIdAsync(request.AreaId, tenantId, cancellationToken); - if (area is null) - { - return false; - } - - // 2. 校验门店归属 - if (area.StoreId != request.StoreId) - { - return false; - } - - // 3. 校验区域下无桌码 - var tables = await storeRepository.GetTablesAsync(request.StoreId, tenantId, cancellationToken); - var hasTable = tables.Any(x => x.AreaId == request.AreaId); - if (hasTable) - { - throw new BusinessException(ErrorCodes.Conflict, "区域下仍有桌码,无法删除"); - } - - // 4. 删除 - await storeRepository.DeleteTableAreaAsync(request.AreaId, tenantId, cancellationToken); - await storeRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("删除桌台区域 {AreaId} 对应门店 {StoreId}", request.AreaId, request.StoreId); - - return true; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreTableCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreTableCommandHandler.cs deleted file mode 100644 index 9828253..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/DeleteStoreTableCommandHandler.cs +++ /dev/null @@ -1,36 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 删除桌码处理器。 -/// -public sealed class DeleteStoreTableCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(DeleteStoreTableCommand request, CancellationToken cancellationToken) - { - // 1. 读取桌码 - var tenantId = tenantProvider.GetCurrentTenantId(); - var table = await storeRepository.FindTableByIdAsync(request.TableId, tenantId, cancellationToken); - if (table is null || table.StoreId != request.StoreId) - { - return false; - } - - // 2. 删除 - await storeRepository.DeleteTableAsync(request.TableId, tenantId, cancellationToken); - await storeRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("删除桌码 {TableId} 对应门店 {StoreId}", request.TableId, request.StoreId); - - return true; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ExportStoreTableQRCodesQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ExportStoreTableQRCodesQueryHandler.cs deleted file mode 100644 index 95ead70..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ExportStoreTableQRCodesQueryHandler.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System.IO.Compression; -using System.Linq; -using System.Text; -using MediatR; -using Microsoft.Extensions.Logging; -using QRCoder; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Application.App.Stores.Queries; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 导出桌码二维码处理器。 -/// -public sealed class ExportStoreTableQRCodesQueryHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(ExportStoreTableQRCodesQuery request, CancellationToken cancellationToken) - { - // 1. 校验门店存在 - var tenantId = tenantProvider.GetCurrentTenantId(); - var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken); - if (store is null) - { - return null; - } - - // 2. 获取桌码列表 - var tables = await storeRepository.GetTablesAsync(request.StoreId, tenantId, cancellationToken); - if (request.AreaId.HasValue) - { - tables = tables.Where(x => x.AreaId == request.AreaId.Value).ToList(); - } - - if (tables.Count == 0) - { - return null; - } - - // 3. 生成 ZIP - var template = string.IsNullOrWhiteSpace(request.QrContentTemplate) ? "{code}" : request.QrContentTemplate!; - using var memoryStream = new MemoryStream(); - using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true, Encoding.UTF8)) - { - foreach (var table in tables) - { - var content = BuildPayload(template, table.TableCode); - var svg = RenderSvg(content); - var entry = archive.CreateEntry($"{table.TableCode}.svg", CompressionLevel.Fastest); - using var entryStream = entry.Open(); - using var writer = new StreamWriter(entryStream, Encoding.UTF8); - writer.Write(svg); - } - } - - // 4. 返回导出结果 - var fileName = $"store_{request.StoreId}_tables_{DateTime.UtcNow:yyyyMMddHHmmss}.zip"; - logger.LogInformation("导出门店 {StoreId} 桌码二维码 {Count} 个", request.StoreId, tables.Count); - return new StoreTableExportResult - { - FileName = fileName, - ContentType = "application/zip", - Content = memoryStream.ToArray() - }; - } - - private static string BuildPayload(string template, string tableCode) - { - var payload = template.Replace("{code}", tableCode, StringComparison.OrdinalIgnoreCase); - return string.IsNullOrWhiteSpace(payload) ? tableCode : payload; - } - - private static string RenderSvg(string payload) - { - using var generator = new QRCodeGenerator(); - var data = generator.CreateQrCode(payload, QRCodeGenerator.ECCLevel.Q); - var svg = new SvgQRCode(data); - return svg.GetGraphic(5); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GenerateStoreTablesCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GenerateStoreTablesCommandHandler.cs deleted file mode 100644 index ad2cf70..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GenerateStoreTablesCommandHandler.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System.Linq; -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Entities; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 批量生成桌码处理器。 -/// -public sealed class GenerateStoreTablesCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler> -{ - /// - public async Task> Handle(GenerateStoreTablesCommand request, CancellationToken cancellationToken) - { - // 1. 校验门店存在 - var tenantId = tenantProvider.GetCurrentTenantId(); - var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken); - if (store is null) - { - throw new BusinessException(ErrorCodes.NotFound, "门店不存在"); - } - - // 2. 校验区域归属 - if (request.AreaId.HasValue) - { - var area = await storeRepository.FindTableAreaByIdAsync(request.AreaId.Value, tenantId, cancellationToken); - if (area is null || area.StoreId != request.StoreId) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "桌台区域不存在或不属于该门店"); - } - } - - // 3. 校验桌码唯一性 - var existingTables = await storeRepository.GetTablesAsync(request.StoreId, tenantId, cancellationToken); - var newCodes = Enumerable.Range(request.StartNumber, request.Count) - .Select(i => $"{request.TableCodePrefix.Trim()}{i}") - .ToList(); - var conflicts = existingTables.Where(t => newCodes.Contains(t.TableCode, StringComparer.OrdinalIgnoreCase)).ToList(); - if (conflicts.Count > 0) - { - throw new BusinessException(ErrorCodes.Conflict, "桌码已存在,生成失败"); - } - - // 4. 构建实体 - var tables = newCodes.Select(code => new StoreTable - { - StoreId = request.StoreId, - AreaId = request.AreaId, - TableCode = code, - Capacity = request.DefaultCapacity, - Tags = request.Tags?.Trim() - }).ToList(); - - // 5. 持久化 - await storeRepository.AddTablesAsync(tables, cancellationToken); - await storeRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("批量创建桌码 {Count} 条 对应门店 {StoreId}", tables.Count, request.StoreId); - - // 6. 返回 DTO - return tables.Select(StoreMapping.ToDto).ToList(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GetAvailablePickupSlotsQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GetAvailablePickupSlotsQueryHandler.cs deleted file mode 100644 index bbfb8f7..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GetAvailablePickupSlotsQueryHandler.cs +++ /dev/null @@ -1,83 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Application.App.Stores.Queries; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 可用自提档期查询处理器。 -/// -public sealed class GetAvailablePickupSlotsQueryHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - /// - public async Task> Handle(GetAvailablePickupSlotsQuery request, CancellationToken cancellationToken) - { - var tenantId = tenantProvider.GetCurrentTenantId(); - var date = request.Date.Date; - // 1. 读取配置 - var setting = await storeRepository.GetPickupSettingAsync(request.StoreId, tenantId, cancellationToken); - var allowDays = setting?.AllowDaysAhead ?? 0; - var allowToday = setting?.AllowToday ?? false; - var defaultCutoff = setting?.DefaultCutoffMinutes ?? 30; - - // 2. 校验日期范围 - if (!allowToday && date == DateTime.UtcNow.Date) - { - return []; - } - - if (date > DateTime.UtcNow.Date.AddDays(allowDays)) - { - return []; - } - - // 3. 读取档期 - var slots = await storeRepository.GetPickupSlotsAsync(request.StoreId, tenantId, cancellationToken); - var weekday = (int)date.DayOfWeek; - weekday = weekday == 0 ? 7 : weekday; - var nowUtc = DateTime.UtcNow; - - // 4. 过滤可用 - var available = slots - .Where(x => x.IsEnabled && ContainsDay(x.Weekdays, weekday)) - .Select(slot => - { - var cutoff = slot.CutoffMinutes == 0 ? defaultCutoff : slot.CutoffMinutes; - var slotStartUtc = date.Add(slot.StartTime); - // 判断截单 - var cutoffTime = slotStartUtc.AddMinutes(-cutoff); - var isCutoff = nowUtc > cutoffTime; - var remaining = slot.Capacity - slot.ReservedCount; - return (slot, isCutoff, remaining); - }) - .Where(x => !x.isCutoff && x.remaining > 0) - .Select(x => new StorePickupSlotDto - { - Id = x.slot.Id, - StoreId = x.slot.StoreId, - Name = x.slot.Name, - StartTime = x.slot.StartTime, - EndTime = x.slot.EndTime, - CutoffMinutes = x.slot.CutoffMinutes, - Capacity = x.slot.Capacity, - ReservedCount = x.slot.ReservedCount, - Weekdays = x.slot.Weekdays, - IsEnabled = x.slot.IsEnabled - }) - .ToList(); - - return available; - } - - private static bool ContainsDay(string weekdays, int target) - { - // 解析适用星期 - var parts = weekdays.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); - return parts.Any(p => int.TryParse(p, out var val) && val == target); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GetStoreByIdQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GetStoreByIdQueryHandler.cs deleted file mode 100644 index e8f0841..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GetStoreByIdQueryHandler.cs +++ /dev/null @@ -1,26 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Application.App.Stores.Queries; -using TakeoutSaaS.Domain.Stores.Entities; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 门店详情查询处理器。 -/// -public sealed class GetStoreByIdQueryHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - public async Task Handle(GetStoreByIdQuery request, CancellationToken cancellationToken) - { - var tenantId = tenantProvider.GetCurrentTenantId(); - var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken); - return store == null ? null : StoreMapping.ToDto(store); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GetStoreFeeQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GetStoreFeeQueryHandler.cs deleted file mode 100644 index e2906dc..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GetStoreFeeQueryHandler.cs +++ /dev/null @@ -1,51 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Application.App.Stores.Queries; -using TakeoutSaaS.Domain.Stores.Entities; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 获取门店费用配置处理器。 -/// -public sealed class GetStoreFeeQueryHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - public async Task Handle(GetStoreFeeQuery request, CancellationToken cancellationToken) - { - // 1. 校验门店存在 - var tenantId = tenantProvider.GetCurrentTenantId(); - var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken); - if (store is null) - { - throw new BusinessException(ErrorCodes.NotFound, "门店不存在"); - } - - // 2. (空行后) 查询费用配置 - var fee = await storeRepository.GetStoreFeeAsync(request.StoreId, tenantId, cancellationToken); - if (fee is null) - { - var fallback = new StoreFee - { - StoreId = request.StoreId, - MinimumOrderAmount = 0m, - BaseDeliveryFee = 0m, - PackagingFeeMode = Domain.Stores.Enums.PackagingFeeMode.Fixed, - OrderPackagingFeeMode = Domain.Stores.Enums.OrderPackagingFeeMode.Fixed, - FixedPackagingFee = 0m - }; - return StoreMapping.ToDto(fallback); - } - - // 3. (空行后) 返回结果 - return StoreMapping.ToDto(fee); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GetStorePickupSettingQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GetStorePickupSettingQueryHandler.cs deleted file mode 100644 index f7899e3..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GetStorePickupSettingQueryHandler.cs +++ /dev/null @@ -1,37 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Application.App.Stores.Queries; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 获取自提配置处理器。 -/// -public sealed class GetStorePickupSettingQueryHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - public async Task Handle(GetStorePickupSettingQuery request, CancellationToken cancellationToken) - { - var tenantId = tenantProvider.GetCurrentTenantId(); - var setting = await storeRepository.GetPickupSettingAsync(request.StoreId, tenantId, cancellationToken); - if (setting is null) - { - return null; - } - - return new StorePickupSettingDto - { - Id = setting.Id, - StoreId = setting.StoreId, - AllowToday = setting.AllowToday, - AllowDaysAhead = setting.AllowDaysAhead, - DefaultCutoffMinutes = setting.DefaultCutoffMinutes, - MaxQuantityPerOrder = setting.MaxQuantityPerOrder - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GetStoreTableContextQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GetStoreTableContextQueryHandler.cs deleted file mode 100644 index 8ef1bea..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GetStoreTableContextQueryHandler.cs +++ /dev/null @@ -1,55 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Application.App.Stores.Queries; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 桌码上下文查询处理器。 -/// -public sealed class GetStoreTableContextQueryHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(GetStoreTableContextQuery request, CancellationToken cancellationToken) - { - // 1. 查询桌码 - var tenantId = tenantProvider.GetCurrentTenantId(); - var table = await storeRepository.FindTableByCodeAsync(request.TableCode, tenantId, cancellationToken); - if (table is null) - { - logger.LogWarning("未找到桌码 {TableCode}", request.TableCode); - return null; - } - - // 2. 查询门店 - var store = await storeRepository.FindByIdAsync(table.StoreId, tenantId, cancellationToken); - if (store is null) - { - throw new BusinessException(ErrorCodes.NotFound, "门店不存在"); - } - - // 3. 组装上下文 - return new StoreTableContextDto - { - StoreId = store.Id, - StoreName = store.Name, - Announcement = store.Announcement, - Tags = store.Tags, - TableId = table.Id, - TableCode = table.TableCode, - AreaId = table.AreaId, - Capacity = table.Capacity, - TableTags = table.Tags, - Status = table.Status - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListExpiringStoreQualificationsQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListExpiringStoreQualificationsQueryHandler.cs deleted file mode 100644 index 610d2b7..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListExpiringStoreQualificationsQueryHandler.cs +++ /dev/null @@ -1,287 +0,0 @@ -using System.Data; -using System.Data.Common; -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Application.App.Stores.Queries; -using TakeoutSaaS.Domain.Stores.Enums; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Data; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 资质预警查询处理器。 -/// -public sealed class ListExpiringStoreQualificationsQueryHandler( - IDapperExecutor dapperExecutor, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - public async Task Handle( - ListExpiringStoreQualificationsQuery request, - CancellationToken cancellationToken) - { - // 1. 规范化参数 - var page = request.Page <= 0 ? 1 : request.Page; - var pageSize = request.PageSize is <= 0 or > 200 ? 20 : request.PageSize; - var daysThreshold = request.DaysThreshold is null or <= 0 ? 30 : request.DaysThreshold.Value; - if (daysThreshold > 365) - { - daysThreshold = 365; - } - var offset = (page - 1) * pageSize; - var now = DateOnly.FromDateTime(DateTime.UtcNow); - var expiringBefore = now.AddDays(daysThreshold); - - // 2. (空行后) 读取当前租户并校验跨租户 - var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (currentTenantId <= 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识"); - } - - if (request.TenantId.HasValue && request.TenantId.Value != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户查询资质预警"); - } - var tenantId = currentTenantId; - - // 3. (空行后) 执行查询 - return await dapperExecutor.QueryAsync( - DatabaseConstants.AppDataSource, - DatabaseConnectionRole.Read, - async (connection, token) => - { - // 3.1 统计汇总 - var summary = await ExecuteSummaryAsync(connection, now, expiringBefore, tenantId, token); - - // 3.2 (空行后) 统计总数 - var total = await ExecuteScalarIntAsync( - connection, - BuildCountSql(), - [ - ("tenantId", tenantId), - ("expiredOnly", request.Expired), - ("now", now), - ("expiringBefore", expiringBefore) - ], - token); - if (total == 0) - { - return BuildResult([], page, pageSize, total, summary); - } - - // 3.3 (空行后) 查询列表 - await using var listCommand = CreateCommand( - connection, - BuildListSql(), - [ - ("tenantId", tenantId), - ("expiredOnly", request.Expired), - ("now", now), - ("expiringBefore", expiringBefore), - ("offset", offset), - ("limit", pageSize) - ]); - - await using var reader = await listCommand.ExecuteReaderAsync(token); - if (!reader.HasRows) - { - return BuildResult([], page, pageSize, total, summary); - } - - // 3.4 (空行后) 初始化字段序号 - var qualificationIdOrdinal = reader.GetOrdinal("QualificationId"); - var storeIdOrdinal = reader.GetOrdinal("StoreId"); - var storeNameOrdinal = reader.GetOrdinal("StoreName"); - var storeCodeOrdinal = reader.GetOrdinal("StoreCode"); - var tenantIdOrdinal = reader.GetOrdinal("TenantId"); - var tenantNameOrdinal = reader.GetOrdinal("TenantName"); - var typeOrdinal = reader.GetOrdinal("QualificationType"); - var expiresAtOrdinal = reader.GetOrdinal("ExpiresAt"); - var businessStatusOrdinal = reader.GetOrdinal("BusinessStatus"); - - // 3.5 (空行后) 读取并映射 - List items = []; - while (await reader.ReadAsync(token)) - { - DateOnly? expiresAt = reader.IsDBNull(expiresAtOrdinal) - ? null - : DateOnly.FromDateTime(reader.GetDateTime(expiresAtOrdinal)); - var isExpired = expiresAt.HasValue && expiresAt.Value < now; - int? daysUntilExpiry = expiresAt.HasValue - ? expiresAt.Value.DayNumber - now.DayNumber - : null; - - items.Add(new StoreQualificationAlertDto - { - QualificationId = reader.GetInt64(qualificationIdOrdinal), - StoreId = reader.GetInt64(storeIdOrdinal), - StoreName = reader.GetString(storeNameOrdinal), - StoreCode = reader.GetString(storeCodeOrdinal), - TenantId = reader.GetInt64(tenantIdOrdinal), - TenantName = reader.GetString(tenantNameOrdinal), - QualificationType = (StoreQualificationType)reader.GetInt32(typeOrdinal), - ExpiresAt = expiresAt, - DaysUntilExpiry = daysUntilExpiry, - IsExpired = isExpired, - StoreBusinessStatus = (StoreBusinessStatus)reader.GetInt32(businessStatusOrdinal) - }); - } - - // 3.6 (空行后) 组装结果 - return BuildResult(items, page, pageSize, total, summary); - }, - cancellationToken); - } - - private static StoreQualificationAlertResultDto BuildResult( - IReadOnlyList items, - int page, - int pageSize, - int totalCount, - StoreQualificationAlertSummaryDto summary) - { - // 1. 计算总页数 - var totalPages = pageSize == 0 ? 0 : (int)Math.Ceiling(totalCount / (double)pageSize); - - // 2. (空行后) 组装分页结果 - return new StoreQualificationAlertResultDto - { - Items = items, - Page = page, - PageSize = pageSize, - TotalCount = totalCount, - TotalPages = totalPages, - Summary = summary - }; - } - - private static async Task ExecuteSummaryAsync( - IDbConnection connection, - DateOnly now, - DateOnly expiringBefore, - long tenantId, - CancellationToken cancellationToken) - { - await using var command = CreateCommand( - connection, - BuildSummarySql(), - [ - ("tenantId", tenantId), - ("now", now), - ("expiringBefore", expiringBefore) - ]); - - await using var reader = await command.ExecuteReaderAsync(cancellationToken); - if (!reader.HasRows || !await reader.ReadAsync(cancellationToken)) - { - return new StoreQualificationAlertSummaryDto(); - } - - // 1. (空行后) 读取统计结果 - var expiringSoonOrdinal = reader.GetOrdinal("ExpiringSoonCount"); - var expiredOrdinal = reader.GetOrdinal("ExpiredCount"); - - return new StoreQualificationAlertSummaryDto - { - ExpiringSoonCount = reader.IsDBNull(expiringSoonOrdinal) ? 0 : reader.GetInt32(expiringSoonOrdinal), - ExpiredCount = reader.IsDBNull(expiredOrdinal) ? 0 : reader.GetInt32(expiredOrdinal) - }; - } - - private static string BuildCountSql() - { - return """ - select count(*) - from public.store_qualifications q - join public.stores s on s."Id" = q."StoreId" and s."DeletedAt" is null - join public.tenants t on t."Id" = s."TenantId" and t."DeletedAt" is null - where q."DeletedAt" is null - and q."ExpiresAt" is not null - and s."TenantId" = @tenantId - and ( - (@expiredOnly::boolean = true and q."ExpiresAt" < @now) - or (@expiredOnly::boolean = false and q."ExpiresAt" <= @expiringBefore) - ); - """; - } - - private static string BuildListSql() - { - return """ - select - q."Id" as "QualificationId", - q."StoreId", - s."Name" as "StoreName", - s."Code" as "StoreCode", - s."TenantId", - t."Name" as "TenantName", - q."QualificationType", - q."ExpiresAt", - s."BusinessStatus" - from public.store_qualifications q - join public.stores s on s."Id" = q."StoreId" and s."DeletedAt" is null - join public.tenants t on t."Id" = s."TenantId" and t."DeletedAt" is null - where q."DeletedAt" is null - and q."ExpiresAt" is not null - and s."TenantId" = @tenantId - and ( - (@expiredOnly::boolean = true and q."ExpiresAt" < @now) - or (@expiredOnly::boolean = false and q."ExpiresAt" <= @expiringBefore) - ) - order by q."ExpiresAt" asc, q."Id" asc - offset @offset - limit @limit; - """; - } - - private static string BuildSummarySql() - { - return """ - select - coalesce(sum(case when q."ExpiresAt" < @now then 1 else 0 end), 0) as "ExpiredCount", - coalesce(sum(case when q."ExpiresAt" >= @now and q."ExpiresAt" <= @expiringBefore then 1 else 0 end), 0) as "ExpiringSoonCount" - from public.store_qualifications q - join public.stores s on s."Id" = q."StoreId" and s."DeletedAt" is null - join public.tenants t on t."Id" = s."TenantId" and t."DeletedAt" is null - where q."DeletedAt" is null - and q."ExpiresAt" is not null - and s."TenantId" = @tenantId; - """; - } - - private static async Task ExecuteScalarIntAsync( - IDbConnection connection, - string sql, - (string Name, object? Value)[] parameters, - CancellationToken cancellationToken) - { - await using var command = CreateCommand(connection, sql, parameters); - var result = await command.ExecuteScalarAsync(cancellationToken); - return result is null or DBNull ? 0 : Convert.ToInt32(result); - } - - private static DbCommand CreateCommand( - IDbConnection connection, - string sql, - (string Name, object? Value)[] parameters) - { - var command = connection.CreateCommand(); - command.CommandText = sql; - - // 1. (空行后) 绑定参数 - foreach (var (name, value) in parameters) - { - var parameter = command.CreateParameter(); - parameter.ParameterName = name; - parameter.Value = value ?? DBNull.Value; - command.Parameters.Add(parameter); - } - - return (DbCommand)command; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreBusinessHoursQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreBusinessHoursQueryHandler.cs deleted file mode 100644 index e50c85b..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreBusinessHoursQueryHandler.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Linq; -using MediatR; -using TakeoutSaaS.Application.App.Stores; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Application.App.Stores.Queries; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 营业时段列表查询处理器。 -/// -public sealed class ListStoreBusinessHoursQueryHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - private readonly IStoreRepository _storeRepository = storeRepository; - private readonly ITenantProvider _tenantProvider = tenantProvider; - - /// - public async Task> Handle(ListStoreBusinessHoursQuery request, CancellationToken cancellationToken) - { - // 1. 查询时段列表 - var tenantId = _tenantProvider.GetCurrentTenantId(); - var hours = await _storeRepository.GetBusinessHoursAsync(request.StoreId, tenantId, cancellationToken); - - // 2. 映射 DTO - return hours.Select(StoreMapping.ToDto).ToList(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreDeliveryZonesQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreDeliveryZonesQueryHandler.cs deleted file mode 100644 index f577811..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreDeliveryZonesQueryHandler.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Linq; -using MediatR; -using TakeoutSaaS.Application.App.Stores; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Application.App.Stores.Queries; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 配送区域列表查询处理器。 -/// -public sealed class ListStoreDeliveryZonesQueryHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - private readonly IStoreRepository _storeRepository = storeRepository; - private readonly ITenantProvider _tenantProvider = tenantProvider; - - /// - public async Task> Handle(ListStoreDeliveryZonesQuery request, CancellationToken cancellationToken) - { - // 1. 查询配送区域 - var tenantId = _tenantProvider.GetCurrentTenantId(); - var zones = await _storeRepository.GetDeliveryZonesAsync(request.StoreId, tenantId, cancellationToken); - - // 2. 映射 DTO - return zones.Select(StoreMapping.ToDto).ToList(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreEmployeeShiftsQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreEmployeeShiftsQueryHandler.cs deleted file mode 100644 index 2dde5dd..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreEmployeeShiftsQueryHandler.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Linq; -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Application.App.Stores.Queries; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 排班列表查询处理器。 -/// -public sealed class ListStoreEmployeeShiftsQueryHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - /// - public async Task> Handle(ListStoreEmployeeShiftsQuery request, CancellationToken cancellationToken) - { - // 1. 时间范围 - var from = request.From ?? DateTime.UtcNow.Date; - var to = request.To ?? from.AddDays(7); - var tenantId = tenantProvider.GetCurrentTenantId(); - - // 2. 查询排班 - var shifts = await storeRepository.GetShiftsAsync(request.StoreId, tenantId, from, to, cancellationToken); - - if (request.StaffId.HasValue) - { - shifts = shifts.Where(x => x.StaffId == request.StaffId.Value).ToList(); - } - - // 3. 映射 DTO - return shifts.Select(StoreMapping.ToDto).ToList(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreHolidaysQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreHolidaysQueryHandler.cs deleted file mode 100644 index 19a5414..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreHolidaysQueryHandler.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Linq; -using MediatR; -using TakeoutSaaS.Application.App.Stores; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Application.App.Stores.Queries; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 门店节假日列表查询处理器。 -/// -public sealed class ListStoreHolidaysQueryHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - private readonly IStoreRepository _storeRepository = storeRepository; - private readonly ITenantProvider _tenantProvider = tenantProvider; - - /// - public async Task> Handle(ListStoreHolidaysQuery request, CancellationToken cancellationToken) - { - // 1. 查询节假日 - var tenantId = _tenantProvider.GetCurrentTenantId(); - var holidays = await _storeRepository.GetHolidaysAsync(request.StoreId, tenantId, cancellationToken); - - // 2. 映射 DTO - return holidays.Select(StoreMapping.ToDto).ToList(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStorePickupSlotsQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStorePickupSlotsQueryHandler.cs deleted file mode 100644 index 146a7a4..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStorePickupSlotsQueryHandler.cs +++ /dev/null @@ -1,38 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Application.App.Stores.Queries; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 自提档期列表查询处理器。 -/// -public sealed class ListStorePickupSlotsQueryHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - /// - public async Task> Handle(ListStorePickupSlotsQuery request, CancellationToken cancellationToken) - { - var tenantId = tenantProvider.GetCurrentTenantId(); - var slots = await storeRepository.GetPickupSlotsAsync(request.StoreId, tenantId, cancellationToken); - return slots - .Select(x => new StorePickupSlotDto - { - Id = x.Id, - StoreId = x.StoreId, - Name = x.Name, - StartTime = x.StartTime, - EndTime = x.EndTime, - CutoffMinutes = x.CutoffMinutes, - Capacity = x.Capacity, - ReservedCount = x.ReservedCount, - Weekdays = x.Weekdays, - IsEnabled = x.IsEnabled - }) - .ToList(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreQualificationsQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreQualificationsQueryHandler.cs deleted file mode 100644 index 9db1132..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreQualificationsQueryHandler.cs +++ /dev/null @@ -1,37 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Application.App.Stores.Queries; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 门店资质列表查询处理器。 -/// -public sealed class ListStoreQualificationsQueryHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - /// - public async Task> Handle(ListStoreQualificationsQuery request, CancellationToken cancellationToken) - { - // 1. 校验门店存在 - var tenantId = tenantProvider.GetCurrentTenantId(); - var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken); - if (store is null) - { - throw new BusinessException(ErrorCodes.NotFound, "门店不存在"); - } - - // 2. (空行后) 读取资质列表 - var qualifications = await storeRepository.GetQualificationsAsync(request.StoreId, tenantId, cancellationToken); - - // 3. (空行后) 映射 DTO - return qualifications.Select(StoreMapping.ToDto).ToList(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreStaffQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreStaffQueryHandler.cs deleted file mode 100644 index 5a2e770..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreStaffQueryHandler.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System.Linq; -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Application.App.Stores.Queries; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 门店员工列表查询处理器。 -/// -public sealed class ListStoreStaffQueryHandler( - IMerchantRepository merchantRepository, - IStoreRepository storeRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - /// - public async Task> Handle(ListStoreStaffQuery request, CancellationToken cancellationToken) - { - // 1. 校验门店存在 - var tenantId = tenantProvider.GetCurrentTenantId(); - var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken); - if (store is null) - { - return []; - } - - // 2. 查询员工 - var staffs = await merchantRepository.GetStaffByStoreAsync(request.StoreId, tenantId, cancellationToken); - - if (request.RoleType.HasValue) - { - staffs = staffs.Where(x => x.RoleType == request.RoleType.Value).ToList(); - } - - if (request.Status.HasValue) - { - staffs = staffs.Where(x => x.Status == request.Status.Value).ToList(); - } - - // 3. 映射 DTO - return staffs.Select(StoreMapping.ToDto).ToList(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreTableAreasQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreTableAreasQueryHandler.cs deleted file mode 100644 index 5de8fa5..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreTableAreasQueryHandler.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Linq; -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Application.App.Stores.Queries; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 桌台区域列表查询处理器。 -/// -public sealed class ListStoreTableAreasQueryHandler(IStoreRepository storeRepository, ITenantProvider tenantProvider) - : IRequestHandler> -{ - /// - public async Task> Handle(ListStoreTableAreasQuery request, CancellationToken cancellationToken) - { - // 1. 查询区域列表 - var tenantId = tenantProvider.GetCurrentTenantId(); - var areas = await storeRepository.GetTableAreasAsync(request.StoreId, tenantId, cancellationToken); - - // 2. 映射 DTO - return areas.Select(StoreMapping.ToDto).ToList(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreTablesQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreTablesQueryHandler.cs deleted file mode 100644 index 786b67f..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ListStoreTablesQueryHandler.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Linq; -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Application.App.Stores.Queries; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 桌码列表查询处理器。 -/// -public sealed class ListStoreTablesQueryHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - /// - public async Task> Handle(ListStoreTablesQuery request, CancellationToken cancellationToken) - { - // 1. 查询桌码列表 - var tenantId = tenantProvider.GetCurrentTenantId(); - var tables = await storeRepository.GetTablesAsync(request.StoreId, tenantId, cancellationToken); - - // 2. 过滤 - if (request.AreaId.HasValue) - { - tables = tables.Where(x => x.AreaId == request.AreaId.Value).ToList(); - } - - if (request.Status.HasValue) - { - tables = tables.Where(x => x.Status == request.Status.Value).ToList(); - } - - // 3. 映射 DTO - return tables.Select(StoreMapping.ToDto).ToList(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/SearchStoresQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/SearchStoresQueryHandler.cs deleted file mode 100644 index e94570c..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/SearchStoresQueryHandler.cs +++ /dev/null @@ -1,57 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Application.App.Stores.Queries; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Results; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 门店列表查询处理器。 -/// -public sealed class SearchStoresQueryHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - /// - public async Task> Handle(SearchStoresQuery request, CancellationToken cancellationToken) - { - var tenantId = tenantProvider.GetCurrentTenantId(); - var stores = await storeRepository.SearchAsync( - tenantId, - request.MerchantId, - request.Status, - request.AuditStatus, - request.BusinessStatus, - request.OwnershipType, - request.Keyword, - cancellationToken); - - var sorted = ApplySorting(stores, request.SortBy, request.SortDescending); - var paged = sorted - .Skip((request.Page - 1) * request.PageSize) - .Take(request.PageSize) - .ToList(); - - var items = paged.Select(StoreMapping.ToDto).ToList(); - return new PagedResult(items, request.Page, request.PageSize, stores.Count); - } - - private static IOrderedEnumerable ApplySorting( - IReadOnlyCollection stores, - string? sortBy, - bool sortDescending) - { - return sortBy?.ToLowerInvariant() switch - { - "name" => sortDescending ? stores.OrderByDescending(x => x.Name) : stores.OrderBy(x => x.Name), - "code" => sortDescending ? stores.OrderByDescending(x => x.Code) : stores.OrderBy(x => x.Code), - "status" => sortDescending ? stores.OrderByDescending(x => x.Status) : stores.OrderBy(x => x.Status), - _ => sortDescending ? stores.OrderByDescending(x => x.CreatedAt) : stores.OrderBy(x => x.CreatedAt) - }; - } - -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/SubmitStoreAuditCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/SubmitStoreAuditCommandHandler.cs deleted file mode 100644 index 90b678e..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/SubmitStoreAuditCommandHandler.cs +++ /dev/null @@ -1,115 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Application.App.Stores.Queries; -using TakeoutSaaS.Domain.Stores.Entities; -using TakeoutSaaS.Domain.Stores.Enums; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 提交门店审核处理器。 -/// -public sealed class SubmitStoreAuditCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ICurrentUserAccessor currentUserAccessor, - IMediator mediator, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(SubmitStoreAuditCommand request, CancellationToken cancellationToken) - { - // 1. 校验门店存在 - var tenantId = tenantProvider.GetCurrentTenantId(); - var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken); - if (store is null) - { - throw new BusinessException(ErrorCodes.NotFound, "门店不存在"); - } - - if (store.AuditStatus is not StoreAuditStatus.Draft and not StoreAuditStatus.Rejected) - { - throw new BusinessException(ErrorCodes.Conflict, "门店不处于可提交状态"); - } - - // 2. (空行后) 处理同主体门店直接激活 - var now = DateTime.UtcNow; - if (store.OwnershipType == StoreOwnershipType.SameEntity) - { - var previousStatus = store.AuditStatus; - store.AuditStatus = StoreAuditStatus.Activated; - store.BusinessStatus = StoreBusinessStatus.Resting; - store.SubmittedAt ??= now; - store.ActivatedAt ??= now; - store.RejectionReason = null; - - await storeRepository.UpdateStoreAsync(store, cancellationToken); - await storeRepository.AddAuditRecordAsync(new StoreAuditRecord - { - StoreId = store.Id, - Action = StoreAuditAction.AutoActivate, - PreviousStatus = previousStatus, - NewStatus = store.AuditStatus, - OperatorId = ResolveOperatorId(), - OperatorName = ResolveOperatorName(), - Remarks = "同主体门店自动激活" - }, cancellationToken); - await storeRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("门店 {StoreId} 同主体自动激活", store.Id); - - return true; - } - - // 3. (空行后) 校验资质完整性 - var checkResult = await mediator.Send(new CheckStoreQualificationsQuery { StoreId = request.StoreId }, cancellationToken); - if (!checkResult.CanSubmitAudit) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "门店资质不完整,无法提交审核"); - } - - // 4. (空行后) 更新审核状态 - var action = store.AuditStatus == StoreAuditStatus.Rejected - ? StoreAuditAction.Resubmit - : StoreAuditAction.Submit; - var previous = store.AuditStatus; - store.AuditStatus = StoreAuditStatus.Pending; - store.BusinessStatus = StoreBusinessStatus.Resting; - store.SubmittedAt = now; - store.RejectionReason = null; - - await storeRepository.UpdateStoreAsync(store, cancellationToken); - await storeRepository.AddAuditRecordAsync(new StoreAuditRecord - { - StoreId = store.Id, - Action = action, - PreviousStatus = previous, - NewStatus = store.AuditStatus, - OperatorId = ResolveOperatorId(), - OperatorName = ResolveOperatorName(), - Remarks = action == StoreAuditAction.Resubmit ? "门店重新提交审核" : "门店提交审核" - }, cancellationToken); - await storeRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("门店 {StoreId} 提交审核", store.Id); - - return true; - } - - private long? ResolveOperatorId() - { - var id = currentUserAccessor.UserId; - return id == 0 ? null : id; - } - - private string ResolveOperatorName() - { - var id = currentUserAccessor.UserId; - return id == 0 ? "system" : $"user:{id}"; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ToggleBusinessStatusCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ToggleBusinessStatusCommandHandler.cs deleted file mode 100644 index 7bf5f61..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/ToggleBusinessStatusCommandHandler.cs +++ /dev/null @@ -1,69 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Enums; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 切换门店经营状态处理器。 -/// -public sealed class ToggleBusinessStatusCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(ToggleBusinessStatusCommand request, CancellationToken cancellationToken) - { - // 1. 校验门店存在 - var tenantId = tenantProvider.GetCurrentTenantId(); - var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken); - if (store is null) - { - throw new BusinessException(ErrorCodes.NotFound, "门店不存在"); - } - - if (store.AuditStatus != StoreAuditStatus.Activated) - { - throw new BusinessException(ErrorCodes.Conflict, "门店未激活,无法切换状态"); - } - - if (store.BusinessStatus == StoreBusinessStatus.ForceClosed) - { - throw new BusinessException(ErrorCodes.Conflict, "门店已被风控强制关闭,无法切换"); - } - - // 2. (空行后) 应用状态变更 - if (request.BusinessStatus == StoreBusinessStatus.Resting) - { - if (!request.ClosureReason.HasValue) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "切换休息中必须选择歇业原因"); - } - - store.BusinessStatus = StoreBusinessStatus.Resting; - store.ClosureReason = request.ClosureReason; - store.ClosureReasonText = request.ClosureReasonText?.Trim(); - } - else - { - store.BusinessStatus = StoreBusinessStatus.Open; - store.ClosureReason = null; - store.ClosureReasonText = null; - } - - // 3. (空行后) 保存并返回 - await storeRepository.UpdateStoreAsync(store, cancellationToken); - await storeRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("切换门店 {StoreId} 状态至 {BusinessStatus}", store.Id, store.BusinessStatus); - - return StoreMapping.ToDto(store); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreBusinessHourCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreBusinessHourCommandHandler.cs deleted file mode 100644 index b85bd55..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreBusinessHourCommandHandler.cs +++ /dev/null @@ -1,59 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Entities; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 更新营业时段处理器。 -/// -public sealed class UpdateStoreBusinessHourCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - private readonly IStoreRepository _storeRepository = storeRepository; - private readonly ITenantProvider _tenantProvider = tenantProvider; - private readonly ILogger _logger = logger; - - /// - public async Task Handle(UpdateStoreBusinessHourCommand request, CancellationToken cancellationToken) - { - // 1. 读取时段 - var tenantId = _tenantProvider.GetCurrentTenantId(); - var existing = await _storeRepository.FindBusinessHourByIdAsync(request.BusinessHourId, tenantId, cancellationToken); - if (existing is null) - { - return null; - } - - // 2. 校验门店归属 - if (existing.StoreId != request.StoreId) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "营业时段不属于该门店"); - } - - // 3. 更新字段 - existing.DayOfWeek = request.DayOfWeek; - existing.HourType = request.HourType; - existing.StartTime = request.StartTime; - existing.EndTime = request.EndTime; - existing.CapacityLimit = request.CapacityLimit; - existing.Notes = request.Notes?.Trim(); - - // 4. 持久化 - await _storeRepository.UpdateBusinessHourAsync(existing, cancellationToken); - await _storeRepository.SaveChangesAsync(cancellationToken); - _logger.LogInformation("更新营业时段 {BusinessHourId} 对应门店 {StoreId}", existing.Id, existing.StoreId); - - // 5. 返回 DTO - return StoreMapping.ToDto(existing); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreCommandHandler.cs deleted file mode 100644 index 69f8133..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreCommandHandler.cs +++ /dev/null @@ -1,79 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Entities; -using TakeoutSaaS.Domain.Stores.Enums; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 更新门店命令处理器。 -/// -public sealed class UpdateStoreCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(UpdateStoreCommand request, CancellationToken cancellationToken) - { - // 1. 读取门店 - var tenantId = tenantProvider.GetCurrentTenantId(); - var existing = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken); - if (existing == null) - { - return null; - } - - // 2. 校验状态是否允许更新 - if (existing.AuditStatus == StoreAuditStatus.Pending) - { - throw new BusinessException(ErrorCodes.Conflict, "门店审核中,暂不允许修改"); - } - - // 2.1 (空行后) 强制关闭门店禁止更新 - if (existing.BusinessStatus == StoreBusinessStatus.ForceClosed) - { - throw new BusinessException(ErrorCodes.Conflict, "门店已被强制关闭,暂不允许修改"); - } - - // 3. (空行后) 更新字段 - existing.MerchantId = request.MerchantId; - existing.Code = request.Code.Trim(); - existing.Name = request.Name.Trim(); - existing.Phone = request.Phone?.Trim(); - existing.ManagerName = request.ManagerName?.Trim(); - existing.Status = request.Status; - existing.SignboardImageUrl = request.SignboardImageUrl?.Trim(); - existing.CategoryId = request.CategoryId; - existing.Province = request.Province?.Trim(); - existing.City = request.City?.Trim(); - existing.District = request.District?.Trim(); - existing.Address = request.Address?.Trim(); - existing.Longitude = request.Longitude; - existing.Latitude = request.Latitude; - existing.Announcement = request.Announcement?.Trim(); - existing.Tags = request.Tags?.Trim(); - existing.DeliveryRadiusKm = request.DeliveryRadiusKm; - existing.SupportsDineIn = request.SupportsDineIn; - existing.SupportsPickup = request.SupportsPickup; - existing.SupportsDelivery = request.SupportsDelivery; - existing.SupportsReservation = request.SupportsReservation; - existing.SupportsQueueing = request.SupportsQueueing; - - // 4. (空行后) 持久化 - await storeRepository.UpdateStoreAsync(existing, cancellationToken); - await storeRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("更新门店 {StoreId} - {StoreName}", existing.Id, existing.Name); - - // 5. (空行后) 返回 DTO - return StoreMapping.ToDto(existing); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreDeliveryZoneCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreDeliveryZoneCommandHandler.cs deleted file mode 100644 index b8443e5..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreDeliveryZoneCommandHandler.cs +++ /dev/null @@ -1,65 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Application.App.Stores.Services; -using TakeoutSaaS.Domain.Stores.Entities; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 更新配送区域处理器。 -/// -public sealed class UpdateStoreDeliveryZoneCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - IGeoJsonValidationService geoJsonValidationService, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(UpdateStoreDeliveryZoneCommand request, CancellationToken cancellationToken) - { - // 1. 读取区域 - var tenantId = tenantProvider.GetCurrentTenantId(); - var existing = await storeRepository.FindDeliveryZoneByIdAsync(request.DeliveryZoneId, tenantId, cancellationToken); - if (existing is null) - { - return null; - } - - // 2. 校验门店归属 - if (existing.StoreId != request.StoreId) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "配送区域不属于该门店"); - } - - // 3. (空行后) 校验 GeoJSON - var validation = geoJsonValidationService.ValidatePolygon(request.PolygonGeoJson); - if (!validation.IsValid) - { - throw new BusinessException(ErrorCodes.ValidationFailed, validation.ErrorMessage ?? "配送范围格式错误"); - } - - // 4. (空行后) 更新字段 - existing.ZoneName = request.ZoneName.Trim(); - existing.PolygonGeoJson = (validation.NormalizedGeoJson ?? request.PolygonGeoJson).Trim(); - existing.MinimumOrderAmount = request.MinimumOrderAmount; - existing.DeliveryFee = request.DeliveryFee; - existing.EstimatedMinutes = request.EstimatedMinutes; - existing.SortOrder = request.SortOrder; - - // 5. (空行后) 持久化 - await storeRepository.UpdateDeliveryZoneAsync(existing, cancellationToken); - await storeRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("更新配送区域 {DeliveryZoneId} 对应门店 {StoreId}", existing.Id, existing.StoreId); - - // 6. (空行后) 返回 DTO - return StoreMapping.ToDto(existing); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreEmployeeShiftCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreEmployeeShiftCommandHandler.cs deleted file mode 100644 index ed2a975..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreEmployeeShiftCommandHandler.cs +++ /dev/null @@ -1,71 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 更新排班处理器。 -/// -public sealed class UpdateStoreEmployeeShiftCommandHandler( - IStoreRepository storeRepository, - IMerchantRepository merchantRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(UpdateStoreEmployeeShiftCommand request, CancellationToken cancellationToken) - { - // 1. 读取排班 - var tenantId = tenantProvider.GetCurrentTenantId(); - var shift = await storeRepository.FindShiftByIdAsync(request.ShiftId, tenantId, cancellationToken); - if (shift is null) - { - return null; - } - - // 2. 校验门店归属 - if (shift.StoreId != request.StoreId) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "排班不属于该门店"); - } - - // 3. 校验员工归属 - var staff = await merchantRepository.FindStaffByIdAsync(request.StaffId, tenantId, cancellationToken); - if (staff is null || (staff.StoreId.HasValue && staff.StoreId != request.StoreId)) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "员工不存在或不属于该门店"); - } - - // 4. 冲突校验 - var shifts = await storeRepository.GetShiftsAsync(request.StoreId, tenantId, request.ShiftDate.Date, request.ShiftDate.Date, cancellationToken); - var hasConflict = shifts.Any(x => x.Id != request.ShiftId && x.StaffId == request.StaffId && x.ShiftDate == request.ShiftDate); - if (hasConflict) - { - throw new BusinessException(ErrorCodes.Conflict, "该员工当日已存在排班"); - } - - // 5. 更新字段 - shift.StaffId = request.StaffId; - shift.ShiftDate = request.ShiftDate.Date; - shift.StartTime = request.StartTime; - shift.EndTime = request.EndTime; - shift.RoleType = request.RoleType; - shift.Notes = request.Notes?.Trim(); - - // 6. 持久化 - await storeRepository.UpdateShiftAsync(shift, cancellationToken); - await storeRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("更新排班 {ShiftId} 员工 {StaffId} 门店 {StoreId}", shift.Id, shift.StaffId, shift.StoreId); - - // 7. 返回 DTO - return StoreMapping.ToDto(shift); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreFeeCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreFeeCommandHandler.cs deleted file mode 100644 index 7665786..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreFeeCommandHandler.cs +++ /dev/null @@ -1,88 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Entities; -using TakeoutSaaS.Domain.Stores.Enums; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 更新门店费用配置处理器。 -/// -public sealed class UpdateStoreFeeCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(UpdateStoreFeeCommand request, CancellationToken cancellationToken) - { - // 1. 校验门店状态 - var tenantId = tenantProvider.GetCurrentTenantId(); - var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken); - if (store is null) - { - throw new BusinessException(ErrorCodes.NotFound, "门店不存在"); - } - var storeTenantId = store.TenantId; - if (store.AuditStatus != StoreAuditStatus.Activated) - { - throw new BusinessException(ErrorCodes.Conflict, "门店未激活,无法配置费用"); - } - if (store.BusinessStatus == StoreBusinessStatus.ForceClosed) - { - throw new BusinessException(ErrorCodes.Conflict, "门店已被强制关闭,无法配置费用"); - } - - // 2. (空行后) 获取或创建费用配置 - var fee = await storeRepository.GetStoreFeeAsync(request.StoreId, tenantId, cancellationToken); - var isNew = fee is null; - fee ??= new StoreFee - { - StoreId = request.StoreId, - TenantId = storeTenantId - }; - - // 3. (空行后) 应用更新字段 - fee.MinimumOrderAmount = request.MinimumOrderAmount; - fee.BaseDeliveryFee = request.DeliveryFee; - fee.PackagingFeeMode = request.PackagingFeeMode; - fee.OrderPackagingFeeMode = request.PackagingFeeMode == PackagingFeeMode.Fixed - ? request.OrderPackagingFeeMode - : OrderPackagingFeeMode.Fixed; - if (request.PackagingFeeMode == PackagingFeeMode.Fixed && request.OrderPackagingFeeMode == OrderPackagingFeeMode.Tiered) - { - var normalizedTiers = StoreFeeTierHelper.Normalize(request.PackagingFeeTiers); - fee.FixedPackagingFee = 0m; - fee.PackagingFeeTiersJson = StoreFeeTierHelper.Serialize(normalizedTiers); - } - else - { - fee.FixedPackagingFee = request.PackagingFeeMode == PackagingFeeMode.Fixed - ? request.FixedPackagingFee ?? 0m - : 0m; - fee.PackagingFeeTiersJson = null; - } - fee.FreeDeliveryThreshold = request.FreeDeliveryThreshold; - - // 4. (空行后) 保存并返回 - if (isNew) - { - await storeRepository.AddStoreFeeAsync(fee, cancellationToken); - } - else - { - await storeRepository.UpdateStoreFeeAsync(fee, cancellationToken); - } - await storeRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("更新门店 {StoreId} 费用配置", request.StoreId); - return StoreMapping.ToDto(fee); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreHolidayCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreHolidayCommandHandler.cs deleted file mode 100644 index afddded..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreHolidayCommandHandler.cs +++ /dev/null @@ -1,73 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Entities; -using TakeoutSaaS.Domain.Stores.Enums; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 更新节假日配置处理器。 -/// -public sealed class UpdateStoreHolidayCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - private readonly IStoreRepository _storeRepository = storeRepository; - private readonly ITenantProvider _tenantProvider = tenantProvider; - private readonly ILogger _logger = logger; - - /// - public async Task Handle(UpdateStoreHolidayCommand request, CancellationToken cancellationToken) - { - // 1. 读取配置 - var tenantId = _tenantProvider.GetCurrentTenantId(); - var existing = await _storeRepository.FindHolidayByIdAsync(request.HolidayId, tenantId, cancellationToken); - if (existing is null) - { - return null; - } - - // 2. 校验门店归属 - if (existing.StoreId != request.StoreId) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "节假日配置不属于该门店"); - } - - // 3. 更新字段 - existing.Date = NormalizeToUtc(request.Date); - existing.EndDate = request.EndDate.HasValue ? NormalizeToUtc(request.EndDate.Value) : null; - existing.IsAllDay = request.IsAllDay; - existing.StartTime = request.StartTime; - existing.EndTime = request.EndTime; - existing.OverrideType = request.OverrideType; - existing.IsClosed = request.OverrideType == OverrideType.Closed; - existing.Reason = request.Reason?.Trim(); - - // 4. 持久化 - await _storeRepository.UpdateHolidayAsync(existing, cancellationToken); - await _storeRepository.SaveChangesAsync(cancellationToken); - _logger.LogInformation("更新节假日 {HolidayId} 对应门店 {StoreId}", existing.Id, existing.StoreId); - - // 5. 返回 DTO - return StoreMapping.ToDto(existing); - } - - private static DateTime NormalizeToUtc(DateTime value) - { - return value.Kind switch - { - DateTimeKind.Utc => value, - DateTimeKind.Local => value.ToUniversalTime(), - _ => DateTime.SpecifyKind(value, DateTimeKind.Utc) - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStorePickupSlotCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStorePickupSlotCommandHandler.cs deleted file mode 100644 index 30355a3..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStorePickupSlotCommandHandler.cs +++ /dev/null @@ -1,57 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 更新自提档期处理器。 -/// -public sealed class UpdateStorePickupSlotCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(UpdateStorePickupSlotCommand request, CancellationToken cancellationToken) - { - // 1. 查询档期 - var tenantId = tenantProvider.GetCurrentTenantId(); - var slot = await storeRepository.FindPickupSlotByIdAsync(request.SlotId, tenantId, cancellationToken); - if (slot is null || slot.StoreId != request.StoreId) - { - return null; - } - - // 2. 更新字段 - slot.Name = request.Name.Trim(); - slot.StartTime = request.StartTime; - slot.EndTime = request.EndTime; - slot.CutoffMinutes = request.CutoffMinutes; - slot.Capacity = request.Capacity; - slot.Weekdays = request.Weekdays; - slot.IsEnabled = request.IsEnabled; - await storeRepository.UpdatePickupSlotAsync(slot, cancellationToken); - await storeRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("更新自提档期 {SlotId}", request.SlotId); - return new StorePickupSlotDto - { - Id = slot.Id, - StoreId = slot.StoreId, - Name = slot.Name, - StartTime = slot.StartTime, - EndTime = slot.EndTime, - CutoffMinutes = slot.CutoffMinutes, - Capacity = slot.Capacity, - ReservedCount = slot.ReservedCount, - Weekdays = slot.Weekdays, - IsEnabled = slot.IsEnabled - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreQualificationCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreQualificationCommandHandler.cs deleted file mode 100644 index 26d86e5..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreQualificationCommandHandler.cs +++ /dev/null @@ -1,79 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Enums; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 更新门店资质处理器。 -/// -public sealed class UpdateStoreQualificationCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(UpdateStoreQualificationCommand request, CancellationToken cancellationToken) - { - // 1. 校验门店存在 - var tenantId = tenantProvider.GetCurrentTenantId(); - var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken); - if (store is null) - { - throw new BusinessException(ErrorCodes.NotFound, "门店不存在"); - } - - // 2. (空行后) 审核中门店禁止修改资质 - if (store.AuditStatus == StoreAuditStatus.Pending) - { - throw new BusinessException(ErrorCodes.Conflict, "门店审核中,无法修改资质"); - } - - // 3. (空行后) 校验资质记录 - var qualification = await storeRepository.FindQualificationByIdAsync(request.QualificationId, tenantId, cancellationToken); - if (qualification is null || qualification.StoreId != request.StoreId) - { - return null; - } - - // 4. (空行后) 更新字段 - if (!string.IsNullOrWhiteSpace(request.FileUrl)) - { - qualification.FileUrl = request.FileUrl.Trim(); - } - - if (request.DocumentNumber is not null) - { - qualification.DocumentNumber = request.DocumentNumber.Trim(); - } - - if (request.IssuedAt.HasValue) - { - qualification.IssuedAt = request.IssuedAt; - } - - if (request.ExpiresAt.HasValue) - { - qualification.ExpiresAt = request.ExpiresAt; - } - - if (request.SortOrder.HasValue) - { - qualification.SortOrder = request.SortOrder.Value; - } - - // 5. (空行后) 保存变更并返回结果 - await storeRepository.UpdateQualificationAsync(qualification, cancellationToken); - await storeRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("更新门店资质 {QualificationId} 对应门店 {StoreId}", qualification.Id, request.StoreId); - - return StoreMapping.ToDto(qualification); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreStaffCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreStaffCommandHandler.cs deleted file mode 100644 index 28c1321..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreStaffCommandHandler.cs +++ /dev/null @@ -1,55 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 更新门店员工处理器。 -/// -public sealed class UpdateStoreStaffCommandHandler( - IMerchantRepository merchantRepository, - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(UpdateStoreStaffCommand request, CancellationToken cancellationToken) - { - // 1. 校验门店 - var tenantId = tenantProvider.GetCurrentTenantId(); - var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken); - if (store is null) - { - return null; - } - - // 2. 读取员工 - var staff = await merchantRepository.FindStaffByIdAsync(request.StaffId, tenantId, cancellationToken); - if (staff is null || staff.StoreId != request.StoreId) - { - return null; - } - - // 3. 更新字段 - staff.Name = request.Name.Trim(); - staff.Phone = request.Phone.Trim(); - staff.Email = request.Email?.Trim(); - staff.RoleType = request.RoleType; - staff.Status = request.Status; - - // 4. 持久化 - await merchantRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("更新门店员工 {StaffId} 门店 {StoreId}", staff.Id, staff.StoreId); - - // 5. 返回 DTO - return StoreMapping.ToDto(staff); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreTableAreaCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreTableAreaCommandHandler.cs deleted file mode 100644 index e488d6b..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreTableAreaCommandHandler.cs +++ /dev/null @@ -1,59 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 更新桌台区域处理器。 -/// -public sealed class UpdateStoreTableAreaCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(UpdateStoreTableAreaCommand request, CancellationToken cancellationToken) - { - // 1. 读取区域 - var tenantId = tenantProvider.GetCurrentTenantId(); - var area = await storeRepository.FindTableAreaByIdAsync(request.AreaId, tenantId, cancellationToken); - if (area is null) - { - return null; - } - - // 2. 校验门店归属 - if (area.StoreId != request.StoreId) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "区域不属于该门店"); - } - - // 3. 名称唯一校验 - var areas = await storeRepository.GetTableAreasAsync(request.StoreId, tenantId, cancellationToken); - var hasDuplicate = areas.Any(x => x.Id != request.AreaId && x.Name.Equals(request.Name, StringComparison.OrdinalIgnoreCase)); - if (hasDuplicate) - { - throw new BusinessException(ErrorCodes.Conflict, "区域名称已存在"); - } - - // 4. 更新字段 - area.Name = request.Name.Trim(); - area.Description = request.Description?.Trim(); - area.SortOrder = request.SortOrder; - - // 5. 持久化 - await storeRepository.UpdateTableAreaAsync(area, cancellationToken); - await storeRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("更新桌台区域 {AreaId} 对应门店 {StoreId}", area.Id, area.StoreId); - - // 6. 返回 DTO - return StoreMapping.ToDto(area); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreTableCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreTableCommandHandler.cs deleted file mode 100644 index b6f8474..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpdateStoreTableCommandHandler.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System.Linq; -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 更新桌码处理器。 -/// -public sealed class UpdateStoreTableCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(UpdateStoreTableCommand request, CancellationToken cancellationToken) - { - // 1. 读取桌码 - var tenantId = tenantProvider.GetCurrentTenantId(); - var table = await storeRepository.FindTableByIdAsync(request.TableId, tenantId, cancellationToken); - if (table is null) - { - return null; - } - - // 2. 校验门店归属 - if (table.StoreId != request.StoreId) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "桌码不属于该门店"); - } - - // 3. 校验区域归属 - if (request.AreaId.HasValue) - { - var area = await storeRepository.FindTableAreaByIdAsync(request.AreaId.Value, tenantId, cancellationToken); - if (area is null || area.StoreId != request.StoreId) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "桌台区域不存在或不属于该门店"); - } - } - - // 4. 校验桌码唯一 - var tables = await storeRepository.GetTablesAsync(request.StoreId, tenantId, cancellationToken); - var exists = tables.Any(x => x.Id != request.TableId && x.TableCode.Equals(request.TableCode, StringComparison.OrdinalIgnoreCase)); - if (exists) - { - throw new BusinessException(ErrorCodes.Conflict, "桌码已存在"); - } - - // 5. 更新字段 - table.AreaId = request.AreaId; - table.TableCode = request.TableCode.Trim(); - table.Capacity = request.Capacity; - table.Tags = request.Tags?.Trim(); - table.Status = request.Status; - - // 6. 持久化 - await storeRepository.UpdateTableAsync(table, cancellationToken); - await storeRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("更新桌码 {TableId} 对应门店 {StoreId}", table.Id, table.StoreId); - - // 7. 返回 DTO - return StoreMapping.ToDto(table); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpsertStorePickupSettingCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpsertStorePickupSettingCommandHandler.cs deleted file mode 100644 index abb8866..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/UpsertStorePickupSettingCommandHandler.cs +++ /dev/null @@ -1,63 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Entities; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Stores.Handlers; - -/// -/// 自提配置维护处理器。 -/// -public sealed class UpsertStorePickupSettingCommandHandler( - IStoreRepository storeRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(UpsertStorePickupSettingCommand request, CancellationToken cancellationToken) - { - // 1. 校验门店存在 - var tenantId = tenantProvider.GetCurrentTenantId(); - var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken); - if (store is null) - { - throw new BusinessException(ErrorCodes.NotFound, "门店不存在"); - } - - // 2. 读取或创建配置 - var setting = await storeRepository.GetPickupSettingAsync(request.StoreId, tenantId, cancellationToken); - if (setting is null) - { - setting = new StorePickupSetting - { - TenantId = tenantId, - StoreId = request.StoreId - }; - await storeRepository.AddPickupSettingAsync(setting, cancellationToken); - } - - // 3. 更新字段 - setting.AllowToday = request.AllowToday; - setting.AllowDaysAhead = request.AllowDaysAhead; - setting.DefaultCutoffMinutes = request.DefaultCutoffMinutes; - setting.MaxQuantityPerOrder = request.MaxQuantityPerOrder; - await storeRepository.UpdatePickupSettingAsync(setting, cancellationToken); - await storeRepository.SaveChangesAsync(cancellationToken); - logger.LogInformation("更新门店 {StoreId} 自提配置", request.StoreId); - return new StorePickupSettingDto - { - Id = setting.Id, - StoreId = setting.StoreId, - AllowToday = setting.AllowToday, - AllowDaysAhead = setting.AllowDaysAhead, - DefaultCutoffMinutes = setting.DefaultCutoffMinutes, - MaxQuantityPerOrder = setting.MaxQuantityPerOrder - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/CalculateStoreFeeQuery.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Queries/CalculateStoreFeeQuery.cs deleted file mode 100644 index 2219baa..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/CalculateStoreFeeQuery.cs +++ /dev/null @@ -1,30 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; - -namespace TakeoutSaaS.Application.App.Stores.Queries; - -/// -/// 费用预览计算查询。 -/// -public sealed record CalculateStoreFeeQuery : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 商品金额。 - /// - public decimal OrderAmount { get; init; } - - /// - /// 商品种类数量。 - /// - public int? ItemCount { get; init; } - - /// - /// 商品列表。 - /// - public IReadOnlyList Items { get; init; } = []; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/CheckStoreDeliveryZoneQuery.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Queries/CheckStoreDeliveryZoneQuery.cs deleted file mode 100644 index 108427b..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/CheckStoreDeliveryZoneQuery.cs +++ /dev/null @@ -1,25 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; - -namespace TakeoutSaaS.Application.App.Stores.Queries; - -/// -/// 配送范围检测查询。 -/// -public sealed record CheckStoreDeliveryZoneQuery : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 经度。 - /// - public double Longitude { get; init; } - - /// - /// 纬度。 - /// - public double Latitude { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/CheckStoreQualificationsQuery.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Queries/CheckStoreQualificationsQuery.cs deleted file mode 100644 index b7100eb..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/CheckStoreQualificationsQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; - -namespace TakeoutSaaS.Application.App.Stores.Queries; - -/// -/// 检查门店资质完整性查询。 -/// -public sealed record CheckStoreQualificationsQuery : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ExportStoreTableQRCodesQuery.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ExportStoreTableQRCodesQuery.cs deleted file mode 100644 index 230fda0..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ExportStoreTableQRCodesQuery.cs +++ /dev/null @@ -1,25 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; - -namespace TakeoutSaaS.Application.App.Stores.Queries; - -/// -/// 导出桌码二维码查询。 -/// -public sealed record ExportStoreTableQRCodesQuery : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 区域筛选。 - /// - public long? AreaId { get; init; } - - /// - /// 内容模板,使用 {code} 占位。 - /// - public string? QrContentTemplate { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/GetAvailablePickupSlotsQuery.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Queries/GetAvailablePickupSlotsQuery.cs deleted file mode 100644 index f3310b8..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/GetAvailablePickupSlotsQuery.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; - -namespace TakeoutSaaS.Application.App.Stores.Queries; - -/// -/// 获取可用自提档期查询。 -/// -public sealed record GetAvailablePickupSlotsQuery : IRequest> -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 目标日期(本地日期部分)。 - /// - public DateTime Date { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/GetStoreByIdQuery.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Queries/GetStoreByIdQuery.cs deleted file mode 100644 index 7f0699e..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/GetStoreByIdQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; - -namespace TakeoutSaaS.Application.App.Stores.Queries; - -/// -/// 获取门店详情查询。 -/// -public sealed class GetStoreByIdQuery : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/GetStoreFeeQuery.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Queries/GetStoreFeeQuery.cs deleted file mode 100644 index f93897d..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/GetStoreFeeQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; - -namespace TakeoutSaaS.Application.App.Stores.Queries; - -/// -/// 获取门店费用配置查询。 -/// -public sealed record GetStoreFeeQuery : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/GetStorePickupSettingQuery.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Queries/GetStorePickupSettingQuery.cs deleted file mode 100644 index f0a4e28..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/GetStorePickupSettingQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; - -namespace TakeoutSaaS.Application.App.Stores.Queries; - -/// -/// 获取门店自提配置查询。 -/// -public sealed record GetStorePickupSettingQuery : IRequest -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/GetStoreTableContextQuery.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Queries/GetStoreTableContextQuery.cs deleted file mode 100644 index 2ed641e..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/GetStoreTableContextQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; - -namespace TakeoutSaaS.Application.App.Stores.Queries; - -/// -/// 桌码上下文查询。 -/// -public sealed record GetStoreTableContextQuery : IRequest -{ - /// - /// 桌码。 - /// - public string TableCode { get; init; } = string.Empty; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListExpiringStoreQualificationsQuery.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListExpiringStoreQualificationsQuery.cs deleted file mode 100644 index 7c4cfd5..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListExpiringStoreQualificationsQuery.cs +++ /dev/null @@ -1,35 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; - -namespace TakeoutSaaS.Application.App.Stores.Queries; - -/// -/// 资质预警分页查询。 -/// -public sealed record ListExpiringStoreQualificationsQuery : IRequest -{ - /// - /// 过期阈值天数(默认 30 天)。 - /// - public int? DaysThreshold { get; init; } - - /// - /// 租户 ID(可选,默认当前租户;禁止跨租户)。 - /// - public long? TenantId { get; init; } - - /// - /// 是否仅显示已过期。 - /// - public bool Expired { get; init; } - - /// - /// 当前页码。 - /// - public int Page { get; init; } = 1; - - /// - /// 每页条数。 - /// - public int PageSize { get; init; } = 20; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreBusinessHoursQuery.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreBusinessHoursQuery.cs deleted file mode 100644 index dac381a..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreBusinessHoursQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; - -namespace TakeoutSaaS.Application.App.Stores.Queries; - -/// -/// 营业时段列表查询。 -/// -public sealed record ListStoreBusinessHoursQuery : IRequest> -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreDeliveryZonesQuery.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreDeliveryZonesQuery.cs deleted file mode 100644 index c3ed9ed..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreDeliveryZonesQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; - -namespace TakeoutSaaS.Application.App.Stores.Queries; - -/// -/// 配送区域列表查询。 -/// -public sealed record ListStoreDeliveryZonesQuery : IRequest> -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreEmployeeShiftsQuery.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreEmployeeShiftsQuery.cs deleted file mode 100644 index 0684b06..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreEmployeeShiftsQuery.cs +++ /dev/null @@ -1,30 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; - -namespace TakeoutSaaS.Application.App.Stores.Queries; - -/// -/// 员工排班列表查询(支持日期区间)。 -/// -public sealed record ListStoreEmployeeShiftsQuery : IRequest> -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 开始日期(含),默认今日。 - /// - public DateTime? From { get; init; } - - /// - /// 结束日期(含),默认今日+7。 - /// - public DateTime? To { get; init; } - - /// - /// 可选员工筛选。 - /// - public long? StaffId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreHolidaysQuery.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreHolidaysQuery.cs deleted file mode 100644 index bf14cd2..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreHolidaysQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; - -namespace TakeoutSaaS.Application.App.Stores.Queries; - -/// -/// 门店节假日列表查询。 -/// -public sealed record ListStoreHolidaysQuery : IRequest> -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStorePickupSlotsQuery.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStorePickupSlotsQuery.cs deleted file mode 100644 index 88660af..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStorePickupSlotsQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; - -namespace TakeoutSaaS.Application.App.Stores.Queries; - -/// -/// 门店档期列表查询。 -/// -public sealed record ListStorePickupSlotsQuery : IRequest> -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreQualificationsQuery.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreQualificationsQuery.cs deleted file mode 100644 index c2803b1..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreQualificationsQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; - -namespace TakeoutSaaS.Application.App.Stores.Queries; - -/// -/// 查询门店资质列表。 -/// -public sealed record ListStoreQualificationsQuery : IRequest> -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreStaffQuery.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreStaffQuery.cs deleted file mode 100644 index 23004f9..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreStaffQuery.cs +++ /dev/null @@ -1,26 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Merchants.Enums; - -namespace TakeoutSaaS.Application.App.Stores.Queries; - -/// -/// 门店员工列表查询。 -/// -public sealed record ListStoreStaffQuery : IRequest> -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 角色筛选。 - /// - public StaffRoleType? RoleType { get; init; } - - /// - /// 状态筛选。 - /// - public StaffStatus? Status { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreTableAreasQuery.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreTableAreasQuery.cs deleted file mode 100644 index 6af7efc..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreTableAreasQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; - -namespace TakeoutSaaS.Application.App.Stores.Queries; - -/// -/// 门店桌台区域列表查询。 -/// -public sealed record ListStoreTableAreasQuery : IRequest> -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreTablesQuery.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreTablesQuery.cs deleted file mode 100644 index 707e915..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/ListStoreTablesQuery.cs +++ /dev/null @@ -1,26 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Enums; - -namespace TakeoutSaaS.Application.App.Stores.Queries; - -/// -/// 门店桌码列表查询。 -/// -public sealed record ListStoreTablesQuery : IRequest> -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 区域筛选。 - /// - public long? AreaId { get; init; } - - /// - /// 状态筛选。 - /// - public StoreTableStatus? Status { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/SearchStoresQuery.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Queries/SearchStoresQuery.cs deleted file mode 100644 index 16532d4..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Queries/SearchStoresQuery.cs +++ /dev/null @@ -1,62 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Enums; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.App.Stores.Queries; - -/// -/// 门店列表查询。 -/// -public sealed class SearchStoresQuery : IRequest> -{ - /// - /// 商户 ID(可选)。 - /// - public long? MerchantId { get; init; } - - /// - /// 状态过滤。 - /// - public StoreStatus? Status { get; init; } - - /// - /// 审核状态过滤。 - /// - public StoreAuditStatus? AuditStatus { get; init; } - - /// - /// 经营状态过滤。 - /// - public StoreBusinessStatus? BusinessStatus { get; init; } - - /// - /// 主体类型过滤。 - /// - public StoreOwnershipType? OwnershipType { get; init; } - - /// - /// 关键词(名称/编码)。 - /// - public string? Keyword { get; init; } - - /// - /// 页码。 - /// - public int Page { get; init; } = 1; - - /// - /// 每页条数。 - /// - public int PageSize { get; init; } = 20; - - /// - /// 排序字段(name/code/status/createdAt)。 - /// - public string? SortBy { get; init; } - - /// - /// 是否倒序。 - /// - public bool SortDescending { get; init; } = true; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Services/GeoJsonValidationResult.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Services/GeoJsonValidationResult.cs deleted file mode 100644 index 5144d14..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Services/GeoJsonValidationResult.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace TakeoutSaaS.Application.App.Stores.Services; - -/// -/// GeoJSON 校验结果。 -/// -public sealed record GeoJsonValidationResult -{ - /// - /// 是否通过校验。 - /// - public bool IsValid { get; init; } - - /// - /// 规范化后的 GeoJSON(自动闭合时输出)。 - /// - public string? NormalizedGeoJson { get; init; } - - /// - /// 错误信息。 - /// - public string? ErrorMessage { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Services/IDeliveryZoneService.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Services/IDeliveryZoneService.cs deleted file mode 100644 index 892c39f..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Services/IDeliveryZoneService.cs +++ /dev/null @@ -1,22 +0,0 @@ -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Entities; - -namespace TakeoutSaaS.Application.App.Stores.Services; - -/// -/// 配送范围检测服务。 -/// -public interface IDeliveryZoneService -{ - /// - /// 检测坐标是否落在配送范围内。 - /// - /// 配送区域列表。 - /// 经度。 - /// 纬度。 - /// 检测结果。 - StoreDeliveryCheckResultDto CheckPointInZones( - IReadOnlyList zones, - double longitude, - double latitude); -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Services/IGeoJsonValidationService.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Services/IGeoJsonValidationService.cs deleted file mode 100644 index 0454921..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Services/IGeoJsonValidationService.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace TakeoutSaaS.Application.App.Stores.Services; - -/// -/// GeoJSON 校验服务。 -/// -public interface IGeoJsonValidationService -{ - /// - /// 校验多边形 GeoJSON 并返回规范化结果。 - /// - /// GeoJSON 字符串。 - /// 校验结果。 - GeoJsonValidationResult ValidatePolygon(string geoJson); -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Services/IStoreFeeCalculationService.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Services/IStoreFeeCalculationService.cs deleted file mode 100644 index e3c4d91..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Services/IStoreFeeCalculationService.cs +++ /dev/null @@ -1,18 +0,0 @@ -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Domain.Stores.Entities; - -namespace TakeoutSaaS.Application.App.Stores.Services; - -/// -/// 门店费用计算服务。 -/// -public interface IStoreFeeCalculationService -{ - /// - /// 计算费用预览。 - /// - /// 门店费用配置。 - /// 计算请求。 - /// 计算结果。 - StoreFeeCalculationResultDto Calculate(StoreFee fee, StoreFeeCalculationRequestDto request); -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Services/IStoreSchedulerService.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Services/IStoreSchedulerService.cs deleted file mode 100644 index bb19174..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Services/IStoreSchedulerService.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace TakeoutSaaS.Application.App.Stores.Services; - -/// -/// 门店定时任务服务。 -/// -public interface IStoreSchedulerService -{ - /// - /// 自动切换门店营业状态。 - /// - /// 当前时间(UTC)。 - /// 取消标记。 - /// 更新的门店数量。 - Task AutoSwitchBusinessStatusAsync(DateTime now, CancellationToken cancellationToken); - - /// - /// 检查门店资质过期并更新状态。 - /// - /// 当前时间(UTC)。 - /// 取消标记。 - /// 更新的门店数量。 - Task CheckQualificationExpiryAsync(DateTime now, CancellationToken cancellationToken); -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/BatchUpdateBusinessHoursCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/BatchUpdateBusinessHoursCommandValidator.cs deleted file mode 100644 index a113b63..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/BatchUpdateBusinessHoursCommandValidator.cs +++ /dev/null @@ -1,40 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Commands; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 批量更新营业时段命令验证器。 -/// -public sealed class BatchUpdateBusinessHoursCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public BatchUpdateBusinessHoursCommandValidator() - { - RuleFor(x => x.StoreId).GreaterThan(0); - - RuleForEach(x => x.Items).ChildRules(item => - { - item.RuleFor(x => x.StartTime).NotNull(); - item.RuleFor(x => x.EndTime).NotNull(); - item.RuleFor(x => x.CapacityLimit).GreaterThanOrEqualTo(0).When(x => x.CapacityLimit.HasValue); - item.RuleFor(x => x.Notes).MaximumLength(256); - }); - - RuleFor(x => x.Items).Custom((items, context) => - { - if (items == null || items.Count == 0) - { - return; - } - - var error = BusinessHourValidators.ValidateOverlap(items); - if (!string.IsNullOrWhiteSpace(error)) - { - context.AddFailure(error); - } - }); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/BusinessHourValidators.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/BusinessHourValidators.cs deleted file mode 100644 index 1a6f2c8..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/BusinessHourValidators.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System.Linq; -using TakeoutSaaS.Application.App.Stores.Dto; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 营业时段校验助手。 -/// -public static class BusinessHourValidators -{ - /// - /// 校验营业时段是否存在重叠。 - /// - /// 营业时段列表。 - /// 错误信息,若为空表示通过。 - public static string? ValidateOverlap(IReadOnlyList items) - { - if (items.Count == 0) - { - return null; - } - - var segments = new List<(DayOfWeek Day, TimeSpan Start, TimeSpan End)>(); - foreach (var item in items) - { - if (item.StartTime == item.EndTime) - { - return "营业时段开始时间不能等于结束时间"; - } - - if (item.StartTime < item.EndTime) - { - segments.Add((item.DayOfWeek, item.StartTime, item.EndTime)); - continue; - } - - var nextDay = NextDay(item.DayOfWeek); - segments.Add((item.DayOfWeek, item.StartTime, TimeSpan.FromDays(1))); - segments.Add((nextDay, TimeSpan.Zero, item.EndTime)); - } - - var grouped = segments.GroupBy(x => x.Day).ToList(); - foreach (var group in grouped) - { - var ordered = group.OrderBy(x => x.Start).ToList(); - for (var index = 0; index < ordered.Count - 1; index++) - { - var current = ordered[index]; - var next = ordered[index + 1]; - if (next.Start < current.End) - { - return "营业时段存在重叠,请调整"; - } - } - } - - return null; - } - - private static DayOfWeek NextDay(DayOfWeek day) - { - var next = (int)day + 1; - return next > 6 ? DayOfWeek.Sunday : (DayOfWeek)next; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CalculateStoreFeeQueryValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CalculateStoreFeeQueryValidator.cs deleted file mode 100644 index 5b51ad6..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CalculateStoreFeeQueryValidator.cs +++ /dev/null @@ -1,26 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Queries; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 费用预览计算查询验证器。 -/// -public sealed class CalculateStoreFeeQueryValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public CalculateStoreFeeQueryValidator() - { - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.OrderAmount).GreaterThanOrEqualTo(0); - - RuleForEach(x => x.Items).ChildRules(item => - { - item.RuleFor(x => x.SkuId).GreaterThan(0); - item.RuleFor(x => x.Quantity).GreaterThan(0); - item.RuleFor(x => x.PackagingFee).GreaterThanOrEqualTo(0); - }); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CheckStoreDeliveryZoneQueryValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CheckStoreDeliveryZoneQueryValidator.cs deleted file mode 100644 index 0d62c63..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CheckStoreDeliveryZoneQueryValidator.cs +++ /dev/null @@ -1,20 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Queries; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 配送范围检测查询验证器。 -/// -public sealed class CheckStoreDeliveryZoneQueryValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public CheckStoreDeliveryZoneQueryValidator() - { - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.Longitude).InclusiveBetween(-180, 180); - RuleFor(x => x.Latitude).InclusiveBetween(-90, 90); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreBusinessHourCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreBusinessHourCommandValidator.cs deleted file mode 100644 index 2eec370..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreBusinessHourCommandValidator.cs +++ /dev/null @@ -1,21 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Commands; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 创建营业时段命令验证器。 -/// -public sealed class CreateStoreBusinessHourCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public CreateStoreBusinessHourCommandValidator() - { - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.StartTime).NotEqual(x => x.EndTime).WithMessage("开始时间不能等于结束时间"); - RuleFor(x => x.CapacityLimit).GreaterThanOrEqualTo(0).When(x => x.CapacityLimit.HasValue); - RuleFor(x => x.Notes).MaximumLength(256); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreCommandValidator.cs deleted file mode 100644 index e513072..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreCommandValidator.cs +++ /dev/null @@ -1,33 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Commands; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 创建门店命令验证器。 -/// -public sealed class CreateStoreCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public CreateStoreCommandValidator() - { - RuleFor(x => x.MerchantId).GreaterThan(0); - RuleFor(x => x.Code).NotEmpty().MaximumLength(32); - RuleFor(x => x.Name).NotEmpty().MaximumLength(128); - RuleFor(x => x.Phone).MaximumLength(32); - RuleFor(x => x.ManagerName).MaximumLength(64); - RuleFor(x => x.SignboardImageUrl).NotEmpty().MaximumLength(500); - RuleFor(x => x.OwnershipType).IsInEnum(); - RuleFor(x => x.Province).MaximumLength(64); - RuleFor(x => x.City).MaximumLength(64); - RuleFor(x => x.District).MaximumLength(64); - RuleFor(x => x.Address).MaximumLength(256); - RuleFor(x => x.Longitude).NotNull(); - RuleFor(x => x.Latitude).NotNull(); - RuleFor(x => x.Announcement).MaximumLength(512); - RuleFor(x => x.Tags).MaximumLength(256); - RuleFor(x => x.DeliveryRadiusKm).GreaterThanOrEqualTo(0); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreDeliveryZoneCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreDeliveryZoneCommandValidator.cs deleted file mode 100644 index b8878e3..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreDeliveryZoneCommandValidator.cs +++ /dev/null @@ -1,24 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Commands; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 创建配送区域命令验证器。 -/// -public sealed class CreateStoreDeliveryZoneCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public CreateStoreDeliveryZoneCommandValidator() - { - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.ZoneName).NotEmpty().MaximumLength(64); - RuleFor(x => x.PolygonGeoJson).NotEmpty(); - RuleFor(x => x.MinimumOrderAmount).GreaterThanOrEqualTo(0).When(x => x.MinimumOrderAmount.HasValue); - RuleFor(x => x.DeliveryFee).GreaterThanOrEqualTo(0).When(x => x.DeliveryFee.HasValue); - RuleFor(x => x.EstimatedMinutes).GreaterThan(0).When(x => x.EstimatedMinutes.HasValue); - RuleFor(x => x.SortOrder).GreaterThanOrEqualTo(0); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreEmployeeShiftCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreEmployeeShiftCommandValidator.cs deleted file mode 100644 index 9a0cb21..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreEmployeeShiftCommandValidator.cs +++ /dev/null @@ -1,22 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Commands; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 创建排班命令验证器。 -/// -public sealed class CreateStoreEmployeeShiftCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public CreateStoreEmployeeShiftCommandValidator() - { - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.StaffId).GreaterThan(0); - RuleFor(x => x.ShiftDate).NotEmpty(); - RuleFor(x => x.StartTime).LessThan(x => x.EndTime).WithMessage("结束时间必须晚于开始时间"); - RuleFor(x => x.Notes).MaximumLength(256); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreHolidayCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreHolidayCommandValidator.cs deleted file mode 100644 index 6bb463e..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreHolidayCommandValidator.cs +++ /dev/null @@ -1,41 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Commands; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 创建节假日命令验证器。 -/// -public sealed class CreateStoreHolidayCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public CreateStoreHolidayCommandValidator() - { - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.Date).NotEmpty(); - - RuleFor(x => x.EndDate) - .GreaterThanOrEqualTo(x => x.Date) - .When(x => x.EndDate.HasValue) - .WithMessage("结束日期不能早于开始日期"); - - RuleFor(x => x.StartTime) - .NotNull() - .When(x => !x.IsAllDay) - .WithMessage("非全天模式下必须填写开始时间"); - - RuleFor(x => x.EndTime) - .NotNull() - .When(x => !x.IsAllDay) - .WithMessage("非全天模式下必须填写结束时间"); - - RuleFor(x => x.EndTime) - .GreaterThan(x => x.StartTime) - .When(x => !x.IsAllDay && x.StartTime.HasValue && x.EndTime.HasValue) - .WithMessage("结束时间必须晚于开始时间"); - - RuleFor(x => x.Reason).MaximumLength(200); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStorePickupSlotCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStorePickupSlotCommandValidator.cs deleted file mode 100644 index 75def24..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStorePickupSlotCommandValidator.cs +++ /dev/null @@ -1,23 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Commands; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 创建自提档期验证器。 -/// -public sealed class CreateStorePickupSlotCommandValidator : AbstractValidator -{ - /// - /// 初始化规则。 - /// - public CreateStorePickupSlotCommandValidator() - { - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.Name).NotEmpty().MaximumLength(64); - RuleFor(x => x.Capacity).GreaterThan(0); - RuleFor(x => x.Weekdays).NotEmpty().MaximumLength(32); - RuleFor(x => x.CutoffMinutes).GreaterThanOrEqualTo(0); - RuleFor(x => x.EndTime).GreaterThan(x => x.StartTime); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreQualificationCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreQualificationCommandValidator.cs deleted file mode 100644 index 43a7373..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreQualificationCommandValidator.cs +++ /dev/null @@ -1,42 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Domain.Stores.Enums; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 创建门店资质命令验证器。 -/// -public sealed class CreateStoreQualificationCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public CreateStoreQualificationCommandValidator() - { - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.QualificationType).IsInEnum(); - RuleFor(x => x.FileUrl).NotEmpty().MaximumLength(500); - RuleFor(x => x.SortOrder).GreaterThanOrEqualTo(0); - RuleFor(x => x.DocumentNumber).MaximumLength(100); - - RuleFor(x => x.ExpiresAt) - .Must(date => date.HasValue && date.Value > DateOnly.FromDateTime(DateTime.UtcNow)) - .When(x => IsLicenseType(x.QualificationType)) - .WithMessage("证照有效期必须晚于今天"); - - RuleFor(x => x.DocumentNumber) - .NotEmpty() - .MinimumLength(2) - .When(x => IsLicenseType(x.QualificationType)) - .WithMessage("证照编号不能为空"); - - RuleFor(x => x.ExpiresAt) - .Must(date => !date.HasValue || date.Value > DateOnly.FromDateTime(DateTime.UtcNow)) - .When(x => !IsLicenseType(x.QualificationType)) - .WithMessage("证照有效期必须晚于今天"); - } - - private static bool IsLicenseType(StoreQualificationType type) - => type is StoreQualificationType.BusinessLicense or StoreQualificationType.FoodServiceLicense; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreStaffCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreStaffCommandValidator.cs deleted file mode 100644 index 7e4e44b..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreStaffCommandValidator.cs +++ /dev/null @@ -1,21 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Commands; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 创建门店员工命令验证器。 -/// -public sealed class CreateStoreStaffCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public CreateStoreStaffCommandValidator() - { - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.Name).NotEmpty().MaximumLength(64); - RuleFor(x => x.Phone).NotEmpty().MaximumLength(32); - RuleFor(x => x.Email).EmailAddress().When(x => !string.IsNullOrWhiteSpace(x.Email)); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreTableAreaCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreTableAreaCommandValidator.cs deleted file mode 100644 index 9f6649b..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/CreateStoreTableAreaCommandValidator.cs +++ /dev/null @@ -1,21 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Commands; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 创建桌台区域命令验证器。 -/// -public sealed class CreateStoreTableAreaCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public CreateStoreTableAreaCommandValidator() - { - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.Name).NotEmpty().MaximumLength(64); - RuleFor(x => x.Description).MaximumLength(256); - RuleFor(x => x.SortOrder).GreaterThanOrEqualTo(0); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/DeleteStorePickupSlotCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/DeleteStorePickupSlotCommandValidator.cs deleted file mode 100644 index a7b70f5..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/DeleteStorePickupSlotCommandValidator.cs +++ /dev/null @@ -1,19 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Commands; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 删除自提档期验证器。 -/// -public sealed class DeleteStorePickupSlotCommandValidator : AbstractValidator -{ - /// - /// 初始化规则。 - /// - public DeleteStorePickupSlotCommandValidator() - { - RuleFor(x => x.SlotId).GreaterThan(0); - RuleFor(x => x.StoreId).GreaterThan(0); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/DeleteStoreQualificationCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/DeleteStoreQualificationCommandValidator.cs deleted file mode 100644 index 7797b76..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/DeleteStoreQualificationCommandValidator.cs +++ /dev/null @@ -1,19 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Commands; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 删除门店资质命令验证器。 -/// -public sealed class DeleteStoreQualificationCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public DeleteStoreQualificationCommandValidator() - { - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.QualificationId).GreaterThan(0); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/GenerateStoreTablesCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/GenerateStoreTablesCommandValidator.cs deleted file mode 100644 index 534caca..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/GenerateStoreTablesCommandValidator.cs +++ /dev/null @@ -1,23 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Commands; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 批量生成桌码命令验证器。 -/// -public sealed class GenerateStoreTablesCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public GenerateStoreTablesCommandValidator() - { - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.TableCodePrefix).NotEmpty().MaximumLength(16); - RuleFor(x => x.StartNumber).GreaterThan(0); - RuleFor(x => x.Count).GreaterThan(0).LessThanOrEqualTo(500); - RuleFor(x => x.DefaultCapacity).GreaterThan(0).LessThanOrEqualTo(50); - RuleFor(x => x.Tags).MaximumLength(128); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/GetStoreTableContextQueryValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/GetStoreTableContextQueryValidator.cs deleted file mode 100644 index bb80b34..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/GetStoreTableContextQueryValidator.cs +++ /dev/null @@ -1,18 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Queries; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 桌码上下文查询验证器。 -/// -public sealed class GetStoreTableContextQueryValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public GetStoreTableContextQueryValidator() - { - RuleFor(x => x.TableCode).NotEmpty().MaximumLength(32); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/SearchStoresQueryValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/SearchStoresQueryValidator.cs deleted file mode 100644 index 67ea047..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/SearchStoresQueryValidator.cs +++ /dev/null @@ -1,20 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Queries; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 门店列表查询验证器。 -/// -public sealed class SearchStoresQueryValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public SearchStoresQueryValidator() - { - RuleFor(x => x.Page).GreaterThan(0); - RuleFor(x => x.PageSize).InclusiveBetween(1, 200); - RuleFor(x => x.SortBy).MaximumLength(64); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/SubmitStoreAuditCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/SubmitStoreAuditCommandValidator.cs deleted file mode 100644 index c3618d2..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/SubmitStoreAuditCommandValidator.cs +++ /dev/null @@ -1,18 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Commands; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 提交门店审核命令验证器。 -/// -public sealed class SubmitStoreAuditCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public SubmitStoreAuditCommandValidator() - { - RuleFor(x => x.StoreId).GreaterThan(0); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/ToggleBusinessStatusCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/ToggleBusinessStatusCommandValidator.cs deleted file mode 100644 index 472db30..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/ToggleBusinessStatusCommandValidator.cs +++ /dev/null @@ -1,29 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Domain.Stores.Enums; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 切换门店经营状态命令验证器。 -/// -public sealed class ToggleBusinessStatusCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public ToggleBusinessStatusCommandValidator() - { - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.BusinessStatus) - .Must(status => status is StoreBusinessStatus.Open or StoreBusinessStatus.Resting) - .WithMessage("仅允许切换营业中或休息中"); - - RuleFor(x => x.ClosureReason) - .NotNull() - .When(x => x.BusinessStatus == StoreBusinessStatus.Resting) - .WithMessage("切换休息中必须选择歇业原因"); - - RuleFor(x => x.ClosureReasonText).MaximumLength(500); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreBusinessHourCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreBusinessHourCommandValidator.cs deleted file mode 100644 index 2e6f967..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreBusinessHourCommandValidator.cs +++ /dev/null @@ -1,22 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Commands; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 更新营业时段命令验证器。 -/// -public sealed class UpdateStoreBusinessHourCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public UpdateStoreBusinessHourCommandValidator() - { - RuleFor(x => x.BusinessHourId).GreaterThan(0); - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.StartTime).NotEqual(x => x.EndTime).WithMessage("开始时间不能等于结束时间"); - RuleFor(x => x.CapacityLimit).GreaterThanOrEqualTo(0).When(x => x.CapacityLimit.HasValue); - RuleFor(x => x.Notes).MaximumLength(256); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreCommandValidator.cs deleted file mode 100644 index 555b0b0..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreCommandValidator.cs +++ /dev/null @@ -1,31 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Commands; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 更新门店命令验证器。 -/// -public sealed class UpdateStoreCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public UpdateStoreCommandValidator() - { - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.MerchantId).GreaterThan(0); - RuleFor(x => x.Code).NotEmpty().MaximumLength(32); - RuleFor(x => x.Name).NotEmpty().MaximumLength(128); - RuleFor(x => x.Phone).MaximumLength(32); - RuleFor(x => x.ManagerName).MaximumLength(64); - RuleFor(x => x.SignboardImageUrl).MaximumLength(500); - RuleFor(x => x.Province).MaximumLength(64); - RuleFor(x => x.City).MaximumLength(64); - RuleFor(x => x.District).MaximumLength(64); - RuleFor(x => x.Address).MaximumLength(256); - RuleFor(x => x.Announcement).MaximumLength(512); - RuleFor(x => x.Tags).MaximumLength(256); - RuleFor(x => x.DeliveryRadiusKm).GreaterThanOrEqualTo(0); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreDeliveryZoneCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreDeliveryZoneCommandValidator.cs deleted file mode 100644 index 5de6927..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreDeliveryZoneCommandValidator.cs +++ /dev/null @@ -1,25 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Commands; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 更新配送区域命令验证器。 -/// -public sealed class UpdateStoreDeliveryZoneCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public UpdateStoreDeliveryZoneCommandValidator() - { - RuleFor(x => x.DeliveryZoneId).GreaterThan(0); - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.ZoneName).NotEmpty().MaximumLength(64); - RuleFor(x => x.PolygonGeoJson).NotEmpty(); - RuleFor(x => x.MinimumOrderAmount).GreaterThanOrEqualTo(0).When(x => x.MinimumOrderAmount.HasValue); - RuleFor(x => x.DeliveryFee).GreaterThanOrEqualTo(0).When(x => x.DeliveryFee.HasValue); - RuleFor(x => x.EstimatedMinutes).GreaterThan(0).When(x => x.EstimatedMinutes.HasValue); - RuleFor(x => x.SortOrder).GreaterThanOrEqualTo(0); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreEmployeeShiftCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreEmployeeShiftCommandValidator.cs deleted file mode 100644 index 53eb742..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreEmployeeShiftCommandValidator.cs +++ /dev/null @@ -1,23 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Commands; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 更新排班命令验证器。 -/// -public sealed class UpdateStoreEmployeeShiftCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public UpdateStoreEmployeeShiftCommandValidator() - { - RuleFor(x => x.ShiftId).GreaterThan(0); - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.StaffId).GreaterThan(0); - RuleFor(x => x.ShiftDate).NotEmpty(); - RuleFor(x => x.StartTime).LessThan(x => x.EndTime).WithMessage("结束时间必须晚于开始时间"); - RuleFor(x => x.Notes).MaximumLength(256); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreFeeCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreFeeCommandValidator.cs deleted file mode 100644 index 2b145bd..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreFeeCommandValidator.cs +++ /dev/null @@ -1,87 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Commands; -using TakeoutSaaS.Domain.Stores.Enums; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 更新门店费用配置命令验证器。 -/// -public sealed class UpdateStoreFeeCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public UpdateStoreFeeCommandValidator() - { - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.MinimumOrderAmount).GreaterThanOrEqualTo(0).LessThanOrEqualTo(9999.99m); - RuleFor(x => x.DeliveryFee).GreaterThanOrEqualTo(0).LessThanOrEqualTo(999.99m); - RuleFor(x => x.FreeDeliveryThreshold).GreaterThanOrEqualTo(0).When(x => x.FreeDeliveryThreshold.HasValue); - - RuleFor(x => x.FixedPackagingFee) - .NotNull() - .When(x => x.PackagingFeeMode == PackagingFeeMode.Fixed && x.OrderPackagingFeeMode == OrderPackagingFeeMode.Fixed) - .WithMessage("总计打包费模式下必须填写固定打包费"); - - RuleFor(x => x.FixedPackagingFee) - .Must(fee => !fee.HasValue || fee.Value <= 99.99m) - .WithMessage("固定打包费不能超过 99.99"); - - RuleFor(x => x.FixedPackagingFee) - .Must(fee => !fee.HasValue || fee.Value >= 0) - .WithMessage("固定打包费不能为负数"); - - RuleFor(x => x) - .Custom((command, context) => - { - if (command.PackagingFeeMode != PackagingFeeMode.Fixed || command.OrderPackagingFeeMode != OrderPackagingFeeMode.Tiered) - { - return; - } - - if (command.PackagingFeeTiers is null || command.PackagingFeeTiers.Count == 0) - { - context.AddFailure("阶梯价模式必须配置至少 1 个区间"); - return; - } - - if (command.PackagingFeeTiers.Count > 10) - { - context.AddFailure("阶梯价最多支持 10 个区间"); - return; - } - - var expectedMin = 0m; - for (var index = 0; index < command.PackagingFeeTiers.Count; index++) - { - var tier = command.PackagingFeeTiers[index]; - if (tier.Fee < 0 || tier.Fee > 99.99m) - { - context.AddFailure($"第 {index + 1} 个阶梯打包费需在 0~99.99 之间"); - return; - } - - if (tier.MaxPrice.HasValue && tier.MaxPrice.Value <= expectedMin) - { - context.AddFailure($"第 {index + 1} 个阶梯上限必须大于 {expectedMin:0.##}"); - return; - } - - if (!tier.MaxPrice.HasValue && index != command.PackagingFeeTiers.Count - 1) - { - context.AddFailure("仅允许最后一个阶梯的上限为空"); - return; - } - - if (tier.MaxPrice.HasValue && tier.MaxPrice.Value > 99999.99m) - { - context.AddFailure($"第 {index + 1} 个阶梯上限不能超过 99999.99"); - return; - } - - expectedMin = tier.MaxPrice ?? expectedMin; - } - }); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreHolidayCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreHolidayCommandValidator.cs deleted file mode 100644 index cc36913..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreHolidayCommandValidator.cs +++ /dev/null @@ -1,42 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Commands; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 更新节假日命令验证器。 -/// -public sealed class UpdateStoreHolidayCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public UpdateStoreHolidayCommandValidator() - { - RuleFor(x => x.HolidayId).GreaterThan(0); - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.Date).NotEmpty(); - - RuleFor(x => x.EndDate) - .GreaterThanOrEqualTo(x => x.Date) - .When(x => x.EndDate.HasValue) - .WithMessage("结束日期不能早于开始日期"); - - RuleFor(x => x.StartTime) - .NotNull() - .When(x => !x.IsAllDay) - .WithMessage("非全天模式下必须填写开始时间"); - - RuleFor(x => x.EndTime) - .NotNull() - .When(x => !x.IsAllDay) - .WithMessage("非全天模式下必须填写结束时间"); - - RuleFor(x => x.EndTime) - .GreaterThan(x => x.StartTime) - .When(x => !x.IsAllDay && x.StartTime.HasValue && x.EndTime.HasValue) - .WithMessage("结束时间必须晚于开始时间"); - - RuleFor(x => x.Reason).MaximumLength(200); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStorePickupSlotCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStorePickupSlotCommandValidator.cs deleted file mode 100644 index 7ae91d0..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStorePickupSlotCommandValidator.cs +++ /dev/null @@ -1,24 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Commands; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 更新自提档期验证器。 -/// -public sealed class UpdateStorePickupSlotCommandValidator : AbstractValidator -{ - /// - /// 初始化规则。 - /// - public UpdateStorePickupSlotCommandValidator() - { - RuleFor(x => x.SlotId).GreaterThan(0); - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.Name).NotEmpty().MaximumLength(64); - RuleFor(x => x.Capacity).GreaterThan(0); - RuleFor(x => x.Weekdays).NotEmpty().MaximumLength(32); - RuleFor(x => x.CutoffMinutes).GreaterThanOrEqualTo(0); - RuleFor(x => x.EndTime).GreaterThan(x => x.StartTime); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreQualificationCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreQualificationCommandValidator.cs deleted file mode 100644 index 66851c4..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreQualificationCommandValidator.cs +++ /dev/null @@ -1,26 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Commands; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 更新门店资质命令验证器。 -/// -public sealed class UpdateStoreQualificationCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public UpdateStoreQualificationCommandValidator() - { - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.QualificationId).GreaterThan(0); - RuleFor(x => x.FileUrl).MaximumLength(500).When(x => !string.IsNullOrWhiteSpace(x.FileUrl)); - RuleFor(x => x.DocumentNumber).MaximumLength(100).When(x => !string.IsNullOrWhiteSpace(x.DocumentNumber)); - RuleFor(x => x.SortOrder).GreaterThanOrEqualTo(0).When(x => x.SortOrder.HasValue); - RuleFor(x => x.ExpiresAt) - .Must(date => !date.HasValue || date.Value > DateOnly.FromDateTime(DateTime.UtcNow)) - .When(x => x.ExpiresAt.HasValue) - .WithMessage("证照有效期必须晚于今天"); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreStaffCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreStaffCommandValidator.cs deleted file mode 100644 index 27794d2..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreStaffCommandValidator.cs +++ /dev/null @@ -1,22 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Commands; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 更新门店员工命令验证器。 -/// -public sealed class UpdateStoreStaffCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public UpdateStoreStaffCommandValidator() - { - RuleFor(x => x.StaffId).GreaterThan(0); - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.Name).NotEmpty().MaximumLength(64); - RuleFor(x => x.Phone).NotEmpty().MaximumLength(32); - RuleFor(x => x.Email).EmailAddress().When(x => !string.IsNullOrWhiteSpace(x.Email)); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreTableAreaCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreTableAreaCommandValidator.cs deleted file mode 100644 index 31d2b98..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreTableAreaCommandValidator.cs +++ /dev/null @@ -1,22 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Commands; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 更新桌台区域命令验证器。 -/// -public sealed class UpdateStoreTableAreaCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public UpdateStoreTableAreaCommandValidator() - { - RuleFor(x => x.AreaId).GreaterThan(0); - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.Name).NotEmpty().MaximumLength(64); - RuleFor(x => x.Description).MaximumLength(256); - RuleFor(x => x.SortOrder).GreaterThanOrEqualTo(0); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreTableCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreTableCommandValidator.cs deleted file mode 100644 index 340453e..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpdateStoreTableCommandValidator.cs +++ /dev/null @@ -1,22 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Commands; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 更新桌码命令验证器。 -/// -public sealed class UpdateStoreTableCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public UpdateStoreTableCommandValidator() - { - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.TableId).GreaterThan(0); - RuleFor(x => x.TableCode).NotEmpty().MaximumLength(32); - RuleFor(x => x.Capacity).GreaterThan(0).LessThanOrEqualTo(50); - RuleFor(x => x.Tags).MaximumLength(128); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpsertStorePickupSettingCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpsertStorePickupSettingCommandValidator.cs deleted file mode 100644 index 2cc3d04..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Validators/UpsertStorePickupSettingCommandValidator.cs +++ /dev/null @@ -1,21 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Stores.Commands; - -namespace TakeoutSaaS.Application.App.Stores.Validators; - -/// -/// 自提配置验证器。 -/// -public sealed class UpsertStorePickupSettingCommandValidator : AbstractValidator -{ - /// - /// 初始化规则。 - /// - public UpsertStorePickupSettingCommandValidator() - { - RuleFor(x => x.StoreId).GreaterThan(0); - RuleFor(x => x.AllowDaysAhead).GreaterThanOrEqualTo(0); - RuleFor(x => x.DefaultCutoffMinutes).GreaterThanOrEqualTo(0); - RuleFor(x => x.MaxQuantityPerOrder).GreaterThan(0).When(x => x.MaxQuantityPerOrder.HasValue); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/BatchExtendSubscriptionsCommand.cs b/src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/BatchExtendSubscriptionsCommand.cs deleted file mode 100644 index 0f2954b..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/BatchExtendSubscriptionsCommand.cs +++ /dev/null @@ -1,72 +0,0 @@ -using MediatR; -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Application.App.Subscriptions.Commands; - -/// -/// 批量延期订阅命令。 -/// -public sealed record BatchExtendSubscriptionsCommand : IRequest -{ - /// - /// 订阅ID列表。 - /// - [Required] - [MinLength(1, ErrorMessage = "至少需要选择一个订阅")] - public IReadOnlyList SubscriptionIds { get; init; } = Array.Empty(); - - /// - /// 延期时长(天)。 - /// - [Range(1, 3650, ErrorMessage = "延期天数必须在1-3650天之间")] - public int? DurationDays { get; init; } - - /// - /// 延期时长(月)。 - /// - [Range(1, 120, ErrorMessage = "延期月数必须在1-120月之间")] - public int? DurationMonths { get; init; } - - /// - /// 备注信息。 - /// - [MaxLength(500)] - public string? Notes { get; init; } -} - -/// -/// 批量延期结果。 -/// -public record BatchExtendResult -{ - /// - /// 成功数量。 - /// - public int SuccessCount { get; init; } - - /// - /// 失败数量。 - /// - public int FailureCount { get; init; } - - /// - /// 失败详情列表。 - /// - public IReadOnlyList Failures { get; init; } = Array.Empty(); -} - -/// -/// 批量操作失败项。 -/// -public record BatchFailureItem -{ - /// - /// 订阅ID。 - /// - public long SubscriptionId { get; init; } - - /// - /// 失败原因。 - /// - public string Reason { get; init; } = string.Empty; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/BatchSendReminderCommand.cs b/src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/BatchSendReminderCommand.cs deleted file mode 100644 index 8c41be6..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/BatchSendReminderCommand.cs +++ /dev/null @@ -1,45 +0,0 @@ -using MediatR; -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Application.App.Subscriptions.Commands; - -/// -/// 批量发送续费提醒命令。 -/// -public sealed record BatchSendReminderCommand : IRequest -{ - /// - /// 订阅ID列表。 - /// - [Required] - [MinLength(1, ErrorMessage = "至少需要选择一个订阅")] - public IReadOnlyList SubscriptionIds { get; init; } = Array.Empty(); - - /// - /// 提醒内容。 - /// - [Required(ErrorMessage = "提醒内容不能为空")] - [MaxLength(1000, ErrorMessage = "提醒内容不能超过1000字符")] - public string ReminderContent { get; init; } = string.Empty; -} - -/// -/// 批量发送提醒结果。 -/// -public record BatchSendReminderResult -{ - /// - /// 成功发送数量。 - /// - public int SuccessCount { get; init; } - - /// - /// 发送失败数量。 - /// - public int FailureCount { get; init; } - - /// - /// 失败详情列表。 - /// - public IReadOnlyList Failures { get; init; } = Array.Empty(); -} diff --git a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/ChangeSubscriptionPlanCommand.cs b/src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/ChangeSubscriptionPlanCommand.cs deleted file mode 100644 index 3b85ae5..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/ChangeSubscriptionPlanCommand.cs +++ /dev/null @@ -1,34 +0,0 @@ -using MediatR; -using System.ComponentModel.DataAnnotations; -using TakeoutSaaS.Application.App.Subscriptions.Dto; - -namespace TakeoutSaaS.Application.App.Subscriptions.Commands; - -/// -/// 变更套餐命令。 -/// -public sealed record ChangeSubscriptionPlanCommand : IRequest -{ - /// - /// 订阅 ID(从路由参数绑定)。 - /// - [Required] - public long SubscriptionId { get; init; } - - /// - /// 目标套餐 ID。 - /// - [Required] - public long TargetPackageId { get; init; } - - /// - /// 是否立即生效,否则在下周期生效。 - /// - public bool Immediate { get; init; } - - /// - /// 备注信息。 - /// - [MaxLength(500)] - public string? Notes { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/ExtendSubscriptionCommand.cs b/src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/ExtendSubscriptionCommand.cs deleted file mode 100644 index 6034e01..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/ExtendSubscriptionCommand.cs +++ /dev/null @@ -1,29 +0,0 @@ -using MediatR; -using System.ComponentModel.DataAnnotations; -using TakeoutSaaS.Application.App.Subscriptions.Dto; - -namespace TakeoutSaaS.Application.App.Subscriptions.Commands; - -/// -/// 延期订阅命令。 -/// -public sealed record ExtendSubscriptionCommand : IRequest -{ - /// - /// 订阅 ID(从路由参数绑定)。 - /// - [Required] - public long SubscriptionId { get; init; } - - /// - /// 延期时长(月)。 - /// - [Range(1, 120)] - public int DurationMonths { get; init; } - - /// - /// 备注信息。 - /// - [MaxLength(500)] - public string? Notes { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/ProcessAutoRenewalCommand.cs b/src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/ProcessAutoRenewalCommand.cs deleted file mode 100644 index 50849d7..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/ProcessAutoRenewalCommand.cs +++ /dev/null @@ -1,33 +0,0 @@ -using MediatR; -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Application.App.Subscriptions.Commands; - -/// -/// 处理自动续费:为开启自动续费且即将到期的订阅生成续费账单。 -/// -public sealed record ProcessAutoRenewalCommand : IRequest -{ - /// - /// 到期前 N 天生成续费账单。 - /// - [Range(0, 365, ErrorMessage = "续费提前天数必须在 0~365 之间")] - public int RenewalDaysBeforeExpiry { get; init; } = 3; -} - -/// -/// 自动续费处理结果。 -/// -public sealed record ProcessAutoRenewalResult -{ - /// - /// 扫描到的候选订阅数量。 - /// - public int CandidateCount { get; init; } - - /// - /// 实际创建的账单数量。 - /// - public int CreatedBillCount { get; init; } -} - diff --git a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/ProcessRenewalRemindersCommand.cs b/src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/ProcessRenewalRemindersCommand.cs deleted file mode 100644 index 701c542..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/ProcessRenewalRemindersCommand.cs +++ /dev/null @@ -1,33 +0,0 @@ -using MediatR; -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Application.App.Subscriptions.Commands; - -/// -/// 处理续费提醒:按到期前指定天数批量创建站内提醒通知(幂等)。 -/// -public sealed record ProcessRenewalRemindersCommand : IRequest -{ - /// - /// 提醒时间点(到期前 N 天)。 - /// - [MinLength(1, ErrorMessage = "至少需要配置一个提醒时间点")] - public IReadOnlyList ReminderDaysBeforeExpiry { get; init; } = [7, 3, 1]; -} - -/// -/// 续费提醒处理结果。 -/// -public sealed record ProcessRenewalRemindersResult -{ - /// - /// 扫描到的候选订阅数量。 - /// - public int CandidateCount { get; init; } - - /// - /// 实际创建的提醒数量。 - /// - public int CreatedReminderCount { get; init; } -} - diff --git a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/ProcessSubscriptionExpiryCommand.cs b/src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/ProcessSubscriptionExpiryCommand.cs deleted file mode 100644 index 9de607e..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/ProcessSubscriptionExpiryCommand.cs +++ /dev/null @@ -1,33 +0,0 @@ -using MediatR; -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Application.App.Subscriptions.Commands; - -/// -/// 处理订阅到期:到期进入宽限期,宽限期结束自动暂停。 -/// -public sealed record ProcessSubscriptionExpiryCommand : IRequest -{ - /// - /// 宽限期天数。 - /// - [Range(0, 365, ErrorMessage = "宽限期天数必须在 0~365 之间")] - public int GracePeriodDays { get; init; } = 7; -} - -/// -/// 订阅到期处理结果。 -/// -public sealed record ProcessSubscriptionExpiryResult -{ - /// - /// 从 Active 进入宽限期的数量。 - /// - public int EnteredGracePeriodCount { get; init; } - - /// - /// 宽限期到期并暂停的数量。 - /// - public int SuspendedCount { get; init; } -} - diff --git a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/UpdateSubscriptionCommand.cs b/src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/UpdateSubscriptionCommand.cs deleted file mode 100644 index dd16fc5..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/UpdateSubscriptionCommand.cs +++ /dev/null @@ -1,28 +0,0 @@ -using MediatR; -using System.ComponentModel.DataAnnotations; -using TakeoutSaaS.Application.App.Subscriptions.Dto; - -namespace TakeoutSaaS.Application.App.Subscriptions.Commands; - -/// -/// 更新订阅基础信息命令。 -/// -public sealed record UpdateSubscriptionCommand : IRequest -{ - /// - /// 订阅 ID(从路由参数绑定)。 - /// - [Required] - public long SubscriptionId { get; init; } - - /// - /// 是否自动续费。 - /// - public bool? AutoRenew { get; init; } - - /// - /// 运营备注信息。 - /// - [MaxLength(500)] - public string? Notes { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/UpdateSubscriptionStatusCommand.cs b/src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/UpdateSubscriptionStatusCommand.cs deleted file mode 100644 index 4e8240b..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Commands/UpdateSubscriptionStatusCommand.cs +++ /dev/null @@ -1,30 +0,0 @@ -using MediatR; -using System.ComponentModel.DataAnnotations; -using TakeoutSaaS.Application.App.Subscriptions.Dto; -using TakeoutSaaS.Domain.Tenants.Enums; - -namespace TakeoutSaaS.Application.App.Subscriptions.Commands; - -/// -/// 更新订阅状态命令。 -/// -public sealed record UpdateSubscriptionStatusCommand : IRequest -{ - /// - /// 订阅 ID(从路由参数绑定)。 - /// - [Required] - public long SubscriptionId { get; init; } - - /// - /// 目标状态。 - /// - [Required] - public SubscriptionStatus Status { get; init; } - - /// - /// 备注信息。 - /// - [MaxLength(500)] - public string? Notes { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Dto/QuotaUsageDto.cs b/src/Application/TakeoutSaaS.Application/App/Subscriptions/Dto/QuotaUsageDto.cs deleted file mode 100644 index 0f36ea6..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Dto/QuotaUsageDto.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Subscriptions.Dto; - -/// -/// 配额使用 DTO。 -/// -public sealed record QuotaUsageDto -{ - /// - /// 配额 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 配额类型。 - /// - public TenantQuotaType QuotaType { get; init; } - - /// - /// 配额上限。 - /// - public decimal LimitValue { get; init; } - - /// - /// 已使用量。 - /// - public decimal UsedValue { get; init; } - - /// - /// 使用率(百分比)。 - /// - public decimal UsagePercentage => LimitValue > 0 ? Math.Round(UsedValue / LimitValue * 100, 2) : 0; - - /// - /// 剩余额度。 - /// - public decimal RemainingValue => Math.Max(0, LimitValue - UsedValue); - - /// - /// 重置周期描述。 - /// - public string? ResetCycle { get; init; } - - /// - /// 最近一次重置时间。 - /// - public DateTime? LastResetAt { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Dto/SubscriptionDetailDto.cs b/src/Application/TakeoutSaaS.Application/App/Subscriptions/Dto/SubscriptionDetailDto.cs deleted file mode 100644 index 2a91720..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Dto/SubscriptionDetailDto.cs +++ /dev/null @@ -1,106 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Subscriptions.Dto; - -/// -/// 订阅详情 DTO。 -/// -public sealed record SubscriptionDetailDto -{ - /// - /// 订阅 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 租户 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 租户名称。 - /// - public string TenantName { get; init; } = string.Empty; - - /// - /// 租户编码。 - /// - public string TenantCode { get; init; } = string.Empty; - - /// - /// 当前套餐 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantPackageId { get; init; } - - /// - /// 当前套餐信息。 - /// - public TenantPackageDto? Package { get; init; } - - /// - /// 排期套餐 ID(下周期生效)。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long? ScheduledPackageId { get; init; } - - /// - /// 排期套餐信息。 - /// - public TenantPackageDto? ScheduledPackage { get; init; } - - /// - /// 订阅状态。 - /// - public SubscriptionStatus Status { get; init; } - - /// - /// 生效时间(UTC)。 - /// - public DateTime EffectiveFrom { get; init; } - - /// - /// 到期时间(UTC)。 - /// - public DateTime EffectiveTo { get; init; } - - /// - /// 下次计费时间。 - /// - public DateTime? NextBillingDate { get; init; } - - /// - /// 是否自动续费。 - /// - public bool AutoRenew { get; init; } - - /// - /// 备注信息。 - /// - public string? Notes { get; init; } - - /// - /// 配额使用情况列表。 - /// - public IReadOnlyList QuotaUsages { get; init; } = []; - - /// - /// 订阅变更历史列表。 - /// - public IReadOnlyList ChangeHistory { get; init; } = []; - - /// - /// 创建时间。 - /// - public DateTime CreatedAt { get; init; } - - /// - /// 更新时间。 - /// - public DateTime? UpdatedAt { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Dto/SubscriptionHistoryDto.cs b/src/Application/TakeoutSaaS.Application/App/Subscriptions/Dto/SubscriptionHistoryDto.cs deleted file mode 100644 index c513263..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Dto/SubscriptionHistoryDto.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Subscriptions.Dto; - -/// -/// 订阅变更历史 DTO。 -/// -public sealed record SubscriptionHistoryDto -{ - /// - /// 历史记录 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 订阅 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantSubscriptionId { get; init; } - - /// - /// 原套餐 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long FromPackageId { get; init; } - - /// - /// 原套餐名称。 - /// - public string FromPackageName { get; init; } = string.Empty; - - /// - /// 新套餐 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long ToPackageId { get; init; } - - /// - /// 新套餐名称。 - /// - public string ToPackageName { get; init; } = string.Empty; - - /// - /// 变更类型。 - /// - public SubscriptionChangeType ChangeType { get; init; } - - /// - /// 生效时间。 - /// - public DateTime EffectiveFrom { get; init; } - - /// - /// 到期时间。 - /// - public DateTime EffectiveTo { get; init; } - - /// - /// 相关费用。 - /// - public decimal? Amount { get; init; } - - /// - /// 币种。 - /// - public string? Currency { get; init; } - - /// - /// 备注。 - /// - public string? Notes { get; init; } - - /// - /// 创建时间。 - /// - public DateTime CreatedAt { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Dto/SubscriptionListDto.cs b/src/Application/TakeoutSaaS.Application/App/Subscriptions/Dto/SubscriptionListDto.cs deleted file mode 100644 index 1cb4d05..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Dto/SubscriptionListDto.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Subscriptions.Dto; - -/// -/// 订阅列表 DTO。 -/// -public sealed record SubscriptionListDto -{ - /// - /// 订阅 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 租户 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 租户名称。 - /// - public string TenantName { get; init; } = string.Empty; - - /// - /// 租户编码。 - /// - public string TenantCode { get; init; } = string.Empty; - - /// - /// 当前套餐 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantPackageId { get; init; } - - /// - /// 当前套餐名称。 - /// - public string PackageName { get; init; } = string.Empty; - - /// - /// 排期套餐 ID(下周期生效)。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long? ScheduledPackageId { get; init; } - - /// - /// 排期套餐名称。 - /// - public string? ScheduledPackageName { get; init; } - - /// - /// 订阅状态。 - /// - public SubscriptionStatus Status { get; init; } - - /// - /// 生效时间(UTC)。 - /// - public DateTime EffectiveFrom { get; init; } - - /// - /// 到期时间(UTC)。 - /// - public DateTime EffectiveTo { get; init; } - - /// - /// 下次计费时间。 - /// - public DateTime? NextBillingDate { get; init; } - - /// - /// 是否自动续费。 - /// - public bool AutoRenew { get; init; } - - /// - /// 备注信息。 - /// - public string? Notes { get; init; } - - /// - /// 创建时间。 - /// - public DateTime CreatedAt { get; init; } - - /// - /// 更新时间。 - /// - public DateTime? UpdatedAt { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/BatchExtendSubscriptionsCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/BatchExtendSubscriptionsCommandHandler.cs deleted file mode 100644 index a617f3f..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/BatchExtendSubscriptionsCommandHandler.cs +++ /dev/null @@ -1,135 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using System.Text.Json; -using TakeoutSaaS.Application.App.Subscriptions.Commands; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Ids; - -namespace TakeoutSaaS.Application.App.Subscriptions.Handlers; - -/// -/// 批量延期订阅命令处理器。 -/// -public sealed class BatchExtendSubscriptionsCommandHandler( - ISubscriptionRepository subscriptionRepository, - IIdGenerator idGenerator, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(BatchExtendSubscriptionsCommand request, CancellationToken cancellationToken) - { - var successCount = 0; - var failures = new List(); - - // 验证参数 - if (!request.DurationDays.HasValue && !request.DurationMonths.HasValue) - { - throw new InvalidOperationException("必须指定延期天数或延期月数"); - } - - // 计算延期时间 - var extendDays = request.DurationDays ?? 0; - var extendMonths = request.DurationMonths ?? 0; - - // 查询所有订阅 - var subscriptions = await subscriptionRepository.FindByIdsAsync( - request.SubscriptionIds, - cancellationToken); - - foreach (var subscriptionId in request.SubscriptionIds) - { - try - { - var subscription = subscriptions.FirstOrDefault(s => s.Id == subscriptionId); - if (subscription == null) - { - failures.Add(new BatchFailureItem - { - SubscriptionId = subscriptionId, - Reason = "订阅不存在" - }); - continue; - } - - // 记录原始到期时间 - var originalEffectiveTo = subscription.EffectiveTo; - - // 计算新的到期时间 - var newEffectiveTo = subscription.EffectiveTo; - if (extendMonths > 0) - { - newEffectiveTo = newEffectiveTo.AddMonths(extendMonths); - } - if (extendDays > 0) - { - newEffectiveTo = newEffectiveTo.AddDays(extendDays); - } - - subscription.EffectiveTo = newEffectiveTo; - - // 更新备注 - if (!string.IsNullOrWhiteSpace(request.Notes)) - { - subscription.Notes = request.Notes; - } - - // 记录变更历史 - var history = new TenantSubscriptionHistory - { - Id = idGenerator.NextId(), - TenantId = subscription.TenantId, - TenantSubscriptionId = subscription.Id, - FromPackageId = subscription.TenantPackageId, - ToPackageId = subscription.TenantPackageId, - ChangeType = SubscriptionChangeType.Renew, - EffectiveFrom = originalEffectiveTo, - EffectiveTo = newEffectiveTo, - Amount = null, - Currency = null, - Notes = request.Notes ?? $"批量延期: {(extendMonths > 0 ? $"{extendMonths}个月" : "")}{(extendDays > 0 ? $"{extendDays}天" : "")}" - }; - - await subscriptionRepository.AddHistoryAsync(history, cancellationToken); - await subscriptionRepository.UpdateAsync(subscription, cancellationToken); - successCount++; - } - catch (Exception ex) - { - logger.LogError(ex, "批量延期订阅失败: SubscriptionId={SubscriptionId}", subscriptionId); - failures.Add(new BatchFailureItem - { - SubscriptionId = subscriptionId, - Reason = $"处理失败: {ex.Message}" - }); - } - } - - // 记录操作日志 - var operationLog = new OperationLog - { - Id = idGenerator.NextId(), - OperationType = "BatchExtend", - TargetType = "Subscription", - TargetIds = JsonSerializer.Serialize(request.SubscriptionIds), - Parameters = JsonSerializer.Serialize(new { request.DurationDays, request.DurationMonths, request.Notes }), - Result = JsonSerializer.Serialize(new { SuccessCount = successCount, FailureCount = failures.Count }), - Success = failures.Count == 0, - CreatedAt = DateTime.UtcNow - }; - - await subscriptionRepository.AddOperationLogAsync(operationLog, cancellationToken); - - // 保存所有更改 - await subscriptionRepository.SaveChangesAsync(cancellationToken); - - return new BatchExtendResult - { - SuccessCount = successCount, - FailureCount = failures.Count, - Failures = failures - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/BatchSendReminderCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/BatchSendReminderCommandHandler.cs deleted file mode 100644 index 95f36b1..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/BatchSendReminderCommandHandler.cs +++ /dev/null @@ -1,104 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using System.Text.Json; -using TakeoutSaaS.Application.App.Subscriptions.Commands; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Ids; - -namespace TakeoutSaaS.Application.App.Subscriptions.Handlers; - -/// -/// 批量发送续费提醒命令处理器。 -/// -public sealed class BatchSendReminderCommandHandler( - ISubscriptionRepository subscriptionRepository, - IIdGenerator idGenerator, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(BatchSendReminderCommand request, CancellationToken cancellationToken) - { - var successCount = 0; - var failures = new List(); - - // 查询所有订阅及租户信息 - var subscriptions = await subscriptionRepository.FindByIdsWithTenantAsync( - request.SubscriptionIds, - cancellationToken); - - foreach (var subscriptionId in request.SubscriptionIds) - { - try - { - var item = subscriptions.FirstOrDefault(s => s.Subscription.Id == subscriptionId); - if (item == null) - { - failures.Add(new BatchFailureItem - { - SubscriptionId = subscriptionId, - Reason = "订阅不存在" - }); - continue; - } - - // 创建通知记录 - var notification = new TenantNotification - { - Id = idGenerator.NextId(), - TenantId = item.Subscription.TenantId, - Title = "续费提醒", - Message = request.ReminderContent, - Severity = TenantNotificationSeverity.Warning, - Channel = TenantNotificationChannel.InApp, - SentAt = DateTime.UtcNow, - ReadAt = null, - CreatedAt = DateTime.UtcNow - }; - - await subscriptionRepository.AddNotificationAsync(notification, cancellationToken); - successCount++; - - logger.LogInformation( - "发送续费提醒: SubscriptionId={SubscriptionId}, TenantId={TenantId}, TenantName={TenantName}", - subscriptionId, item.Subscription.TenantId, item.Tenant.Name); - } - catch (Exception ex) - { - logger.LogError(ex, "发送续费提醒失败: SubscriptionId={SubscriptionId}", subscriptionId); - failures.Add(new BatchFailureItem - { - SubscriptionId = subscriptionId, - Reason = $"发送失败: {ex.Message}" - }); - } - } - - // 记录操作日志 - var operationLog = new OperationLog - { - Id = idGenerator.NextId(), - OperationType = "BatchRemind", - TargetType = "Subscription", - TargetIds = JsonSerializer.Serialize(request.SubscriptionIds), - Parameters = JsonSerializer.Serialize(new { request.ReminderContent }), - Result = JsonSerializer.Serialize(new { SuccessCount = successCount, FailureCount = failures.Count }), - Success = failures.Count == 0, - CreatedAt = DateTime.UtcNow - }; - - await subscriptionRepository.AddOperationLogAsync(operationLog, cancellationToken); - - // 保存所有更改 - await subscriptionRepository.SaveChangesAsync(cancellationToken); - - return new BatchSendReminderResult - { - SuccessCount = successCount, - FailureCount = failures.Count, - Failures = failures - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/ChangeSubscriptionPlanCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/ChangeSubscriptionPlanCommandHandler.cs deleted file mode 100644 index b744a34..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/ChangeSubscriptionPlanCommandHandler.cs +++ /dev/null @@ -1,95 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Subscriptions.Commands; -using TakeoutSaaS.Application.App.Subscriptions.Dto; -using TakeoutSaaS.Application.App.Subscriptions.Queries; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Ids; - -namespace TakeoutSaaS.Application.App.Subscriptions.Handlers; - -/// -/// 变更套餐命令处理器。 -/// -public sealed class ChangeSubscriptionPlanCommandHandler( - ISubscriptionRepository subscriptionRepository, - IIdGenerator idGenerator, - IMediator mediator) - : IRequestHandler -{ - /// - public async Task Handle(ChangeSubscriptionPlanCommand request, CancellationToken cancellationToken) - { - // 1. 查询订阅 - var subscription = await subscriptionRepository.FindByIdAsync( - request.SubscriptionId, - cancellationToken); - - if (subscription == null) - { - return null; - } - - // 2. 记录原套餐ID - var previousPackageId = subscription.TenantPackageId; - - // 3. 根据是否立即生效更新订阅 - if (request.Immediate) - { - // 立即生效:直接更新当前套餐 - subscription.TenantPackageId = request.TargetPackageId; - subscription.ScheduledPackageId = null; - } - else - { - // 下周期生效:设置排期套餐 - subscription.ScheduledPackageId = request.TargetPackageId; - } - - // 4. 更新备注 - if (!string.IsNullOrWhiteSpace(request.Notes)) - { - subscription.Notes = request.Notes; - } - - // 5. 判断变更类型(升级或降级) - var fromPackage = await subscriptionRepository.FindPackageByIdAsync(previousPackageId, cancellationToken); - var toPackage = await subscriptionRepository.FindPackageByIdAsync(request.TargetPackageId, cancellationToken); - - var changeType = SubscriptionChangeType.Upgrade; - if (fromPackage != null && toPackage != null) - { - // 简单根据价格判断升降级 - if (toPackage.MonthlyPrice < fromPackage.MonthlyPrice) - { - changeType = SubscriptionChangeType.Downgrade; - } - } - - // 6. 记录变更历史 - var history = new TenantSubscriptionHistory - { - Id = idGenerator.NextId(), - TenantId = subscription.TenantId, - TenantSubscriptionId = subscription.Id, - FromPackageId = previousPackageId, - ToPackageId = request.TargetPackageId, - ChangeType = changeType, - EffectiveFrom = request.Immediate ? DateTime.UtcNow : subscription.EffectiveTo, - EffectiveTo = subscription.EffectiveTo, - Amount = null, - Currency = null, - Notes = request.Notes ?? (request.Immediate ? "套餐立即变更" : "套餐排期变更") - }; - - await subscriptionRepository.AddHistoryAsync(history, cancellationToken); - - // 7. 保存更改 - await subscriptionRepository.UpdateAsync(subscription, cancellationToken); - await subscriptionRepository.SaveChangesAsync(cancellationToken); - - // 8. 返回更新后的详情 - return await mediator.Send(new GetSubscriptionDetailQuery { SubscriptionId = subscription.Id }, cancellationToken); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/ExtendSubscriptionCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/ExtendSubscriptionCommandHandler.cs deleted file mode 100644 index 2717c86..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/ExtendSubscriptionCommandHandler.cs +++ /dev/null @@ -1,69 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Subscriptions.Commands; -using TakeoutSaaS.Application.App.Subscriptions.Dto; -using TakeoutSaaS.Application.App.Subscriptions.Queries; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Ids; - -namespace TakeoutSaaS.Application.App.Subscriptions.Handlers; - -/// -/// 延期订阅命令处理器。 -/// -public sealed class ExtendSubscriptionCommandHandler( - ISubscriptionRepository subscriptionRepository, - IIdGenerator idGenerator, - IMediator mediator) - : IRequestHandler -{ - /// - public async Task Handle(ExtendSubscriptionCommand request, CancellationToken cancellationToken) - { - // 1. 查询订阅 - var subscription = await subscriptionRepository.FindByIdAsync( - request.SubscriptionId, - cancellationToken); - - if (subscription == null) - { - return null; - } - - // 2. 计算新的到期时间(从当前到期时间延长) - var originalEffectiveTo = subscription.EffectiveTo; - subscription.EffectiveTo = subscription.EffectiveTo.AddMonths(request.DurationMonths); - - // 3. 更新备注 - if (!string.IsNullOrWhiteSpace(request.Notes)) - { - subscription.Notes = request.Notes; - } - - // 4. 记录变更历史(使用 Renew 类型表示延期) - var history = new TenantSubscriptionHistory - { - Id = idGenerator.NextId(), - TenantId = subscription.TenantId, - TenantSubscriptionId = subscription.Id, - FromPackageId = subscription.TenantPackageId, - ToPackageId = subscription.TenantPackageId, - ChangeType = SubscriptionChangeType.Renew, - EffectiveFrom = originalEffectiveTo, - EffectiveTo = subscription.EffectiveTo, - Amount = null, - Currency = null, - Notes = request.Notes ?? $"延期 {request.DurationMonths} 个月" - }; - - await subscriptionRepository.AddHistoryAsync(history, cancellationToken); - - // 5. 保存更改 - await subscriptionRepository.UpdateAsync(subscription, cancellationToken); - await subscriptionRepository.SaveChangesAsync(cancellationToken); - - // 6. 返回更新后的详情 - return await mediator.Send(new GetSubscriptionDetailQuery { SubscriptionId = subscription.Id }, cancellationToken); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/GetSubscriptionDetailQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/GetSubscriptionDetailQueryHandler.cs deleted file mode 100644 index 1644bb9..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/GetSubscriptionDetailQueryHandler.cs +++ /dev/null @@ -1,138 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Subscriptions.Dto; -using TakeoutSaaS.Application.App.Subscriptions.Queries; -using TakeoutSaaS.Application.App.Tenants; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Domain.Tenants.Enums; - -namespace TakeoutSaaS.Application.App.Subscriptions.Handlers; - -/// -/// 订阅详情查询处理器。 -/// -public sealed class GetSubscriptionDetailQueryHandler( - ISubscriptionRepository subscriptionRepository) - : IRequestHandler -{ - /// - public async Task Handle(GetSubscriptionDetailQuery request, CancellationToken cancellationToken) - { - // 1. 查询订阅基础信息 - var detail = await subscriptionRepository.GetDetailAsync( - request.SubscriptionId, - cancellationToken); - - if (detail == null) - { - return null; - } - - // 2. 查询配额使用情况 - var quotaUsages = await subscriptionRepository.GetQuotaUsagesAsync( - detail.Subscription.TenantId, - cancellationToken); - - var quotaUsageDtos = BuildQuotaUsageDtos(detail.Package, quotaUsages); - - // 3. 查询订阅变更历史(关联套餐信息) - var histories = await subscriptionRepository.GetHistoryAsync(request.SubscriptionId, cancellationToken); - - var historyDtos = histories.Select(h => new SubscriptionHistoryDto - { - Id = h.History.Id, - TenantSubscriptionId = h.History.TenantSubscriptionId, - FromPackageId = h.History.FromPackageId, - FromPackageName = h.FromPackageName, - ToPackageId = h.History.ToPackageId, - ToPackageName = h.ToPackageName, - ChangeType = h.History.ChangeType, - EffectiveFrom = h.History.EffectiveFrom, - EffectiveTo = h.History.EffectiveTo, - Amount = h.History.Amount, - Currency = h.History.Currency, - Notes = h.History.Notes, - CreatedAt = h.History.CreatedAt - }).ToList(); - - // 4. 构建返回结果 - return new SubscriptionDetailDto - { - Id = detail.Subscription.Id, - TenantId = detail.Subscription.TenantId, - TenantName = detail.TenantName, - TenantCode = detail.TenantCode, - TenantPackageId = detail.Subscription.TenantPackageId, - Package = detail.Package?.ToDto(), - ScheduledPackageId = detail.Subscription.ScheduledPackageId, - ScheduledPackage = detail.ScheduledPackage?.ToDto(), - Status = detail.Subscription.Status, - EffectiveFrom = detail.Subscription.EffectiveFrom, - EffectiveTo = detail.Subscription.EffectiveTo, - NextBillingDate = detail.Subscription.NextBillingDate, - AutoRenew = detail.Subscription.AutoRenew, - Notes = detail.Subscription.Notes, - QuotaUsages = quotaUsageDtos, - ChangeHistory = historyDtos, - CreatedAt = detail.Subscription.CreatedAt, - UpdatedAt = detail.Subscription.UpdatedAt - }; - } - - private static List BuildQuotaUsageDtos( - TakeoutSaaS.Domain.Tenants.Entities.TenantPackage? package, - IReadOnlyList quotaUsages) - { - var usageByType = quotaUsages - .GroupBy(u => u.QuotaType) - .ToDictionary(g => g.Key, g => g.First()); - - var baselineTypes = new List<(TenantQuotaType Type, decimal LimitValue)>(); - if (package != null) - { - baselineTypes.Add((TenantQuotaType.StoreCount, package.MaxStoreCount.HasValue ? package.MaxStoreCount.Value : 0)); - baselineTypes.Add((TenantQuotaType.AccountCount, package.MaxAccountCount.HasValue ? package.MaxAccountCount.Value : 0)); - baselineTypes.Add((TenantQuotaType.Storage, package.MaxStorageGb.HasValue ? package.MaxStorageGb.Value : 0)); - baselineTypes.Add((TenantQuotaType.SmsCredits, package.MaxSmsCredits.HasValue ? package.MaxSmsCredits.Value : 0)); - baselineTypes.Add((TenantQuotaType.DeliveryOrders, package.MaxDeliveryOrders.HasValue ? package.MaxDeliveryOrders.Value : 0)); - } - - var results = new List(); - - foreach (var (type, limitValue) in baselineTypes) - { - usageByType.TryGetValue(type, out var usage); - results.Add(new QuotaUsageDto - { - Id = usage?.Id ?? 0, - QuotaType = type, - LimitValue = limitValue, - UsedValue = usage?.UsedValue ?? 0, - ResetCycle = usage?.ResetCycle, - LastResetAt = usage?.LastResetAt - }); - } - - // Add any extra quota usages not covered by package fields (e.g. promotion slots). - foreach (var usage in usageByType.Values) - { - if (baselineTypes.Any(x => x.Type == usage.QuotaType)) - { - continue; - } - - results.Add(new QuotaUsageDto - { - Id = usage.Id, - QuotaType = usage.QuotaType, - LimitValue = usage.LimitValue, - UsedValue = usage.UsedValue, - ResetCycle = usage.ResetCycle, - LastResetAt = usage.LastResetAt - }); - } - - return results - .OrderBy(x => (int)x.QuotaType) - .ToList(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/GetSubscriptionListQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/GetSubscriptionListQueryHandler.cs deleted file mode 100644 index d6bfc0f..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/GetSubscriptionListQueryHandler.cs +++ /dev/null @@ -1,61 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Subscriptions.Dto; -using TakeoutSaaS.Application.App.Subscriptions.Queries; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.App.Subscriptions.Handlers; - -/// -/// 订阅分页查询处理器。 -/// -public sealed class GetSubscriptionListQueryHandler( - ISubscriptionRepository subscriptionRepository) - : IRequestHandler> -{ - /// - public async Task> Handle(GetSubscriptionListQuery request, CancellationToken cancellationToken) - { - // 1. 构建查询过滤条件 - var filter = new SubscriptionSearchFilter - { - Status = request.Status, - TenantPackageId = request.TenantPackageId, - TenantId = request.TenantId, - TenantKeyword = request.TenantKeyword, - ExpiringWithinDays = request.ExpiringWithinDays, - AutoRenew = request.AutoRenew, - Page = request.Page, - PageSize = request.PageSize - }; - - // 2. 执行分页查询 - var (items, total) = await subscriptionRepository.SearchPagedAsync( - filter, - cancellationToken); - - // 3. 映射为 DTO - var dtos = items.Select(x => new SubscriptionListDto - { - Id = x.Subscription.Id, - TenantId = x.Subscription.TenantId, - TenantName = x.TenantName, - TenantCode = x.TenantCode, - TenantPackageId = x.Subscription.TenantPackageId, - PackageName = x.PackageName, - ScheduledPackageId = x.Subscription.ScheduledPackageId, - ScheduledPackageName = x.ScheduledPackageName, - Status = x.Subscription.Status, - EffectiveFrom = x.Subscription.EffectiveFrom, - EffectiveTo = x.Subscription.EffectiveTo, - NextBillingDate = x.Subscription.NextBillingDate, - AutoRenew = x.Subscription.AutoRenew, - Notes = x.Subscription.Notes, - CreatedAt = x.Subscription.CreatedAt, - UpdatedAt = x.Subscription.UpdatedAt - }).ToList(); - - // 4. 返回分页结果 - return new PagedResult(dtos, request.Page, request.PageSize, total); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/ProcessAutoRenewalCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/ProcessAutoRenewalCommandHandler.cs deleted file mode 100644 index 960ed10..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/ProcessAutoRenewalCommandHandler.cs +++ /dev/null @@ -1,137 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using System.Text.Json; -using TakeoutSaaS.Application.App.Subscriptions.Commands; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Ids; - -namespace TakeoutSaaS.Application.App.Subscriptions.Handlers; - -/// -/// 自动续费处理器:生成续费账单(幂等)。 -/// -public sealed class ProcessAutoRenewalCommandHandler( - ISubscriptionRepository subscriptionRepository, - ITenantBillingRepository billingRepository, - IIdGenerator idGenerator, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(ProcessAutoRenewalCommand request, CancellationToken cancellationToken) - { - // 1. 计算续费阈值时间 - var now = DateTime.UtcNow; - var renewalThreshold = now.AddDays(request.RenewalDaysBeforeExpiry); - - // 2. 查询候选订阅(含套餐) - var candidates = await subscriptionRepository.FindAutoRenewalCandidatesAsync( - now, - renewalThreshold, - cancellationToken); - var createdBillCount = 0; - - // 3. 遍历候选订阅,生成账单 - foreach (var candidate in candidates) - { - // 3.1 幂等校验:同一周期开始时间只允许存在一张未取消账单 - var periodStart = candidate.Subscription.EffectiveTo; - var exists = await billingRepository.ExistsNotCancelledByPeriodStartAsync( - candidate.Subscription.TenantId, - periodStart, - cancellationToken); - - if (exists) - { - logger.LogInformation( - "自动续费:租户 {TenantId} 订阅 {SubscriptionId} 已存在周期 {PeriodStart} 的续费账单,跳过", - candidate.Subscription.TenantId, - candidate.Subscription.Id, - periodStart); - continue; - } - - // 3.2 计算续费周期(月) - var durationMonths = CalculateDurationMonths(candidate.Subscription.EffectiveFrom, candidate.Subscription.EffectiveTo); - if (durationMonths <= 0) - { - durationMonths = 1; - } - - // 3.3 计算账单周期与金额 - var periodEnd = periodStart.AddMonths(durationMonths); - var amountDue = CalculateRenewalAmount(candidate.Package, durationMonths); - - // 3.4 生成账单(Pending) - var statementNo = $"BILL-{now:yyyyMMddHHmmss}-{candidate.Subscription.TenantId}-{candidate.Subscription.Id}"; - var lineItemsJson = JsonSerializer.Serialize(new - { - PackageName = candidate.Package.Name, - RenewalMonths = durationMonths, - SubscriptionId = candidate.Subscription.Id - }); - - await billingRepository.AddAsync(new TenantBillingStatement - { - Id = idGenerator.NextId(), - TenantId = candidate.Subscription.TenantId, - StatementNo = statementNo, - PeriodStart = periodStart, - PeriodEnd = periodEnd, - AmountDue = amountDue, - AmountPaid = 0, - DueDate = periodStart.AddDays(-1), - LineItemsJson = lineItemsJson, - CreatedAt = now - }, cancellationToken); - - createdBillCount++; - logger.LogInformation( - "自动续费:为租户 {TenantId} 订阅 {SubscriptionId} 生成账单 {StatementNo},金额 {AmountDue},周期 {PeriodStart}~{PeriodEnd}", - candidate.Subscription.TenantId, - candidate.Subscription.Id, - statementNo, - amountDue, - periodStart, - periodEnd); - } - - // 4. 保存账单变更 - if (createdBillCount > 0) - { - await billingRepository.SaveChangesAsync(cancellationToken); - } - - return new ProcessAutoRenewalResult - { - CandidateCount = candidates.Count, - CreatedBillCount = createdBillCount - }; - } - - private static int CalculateDurationMonths(DateTime effectiveFrom, DateTime effectiveTo) - { - // 1. 以年月差作为周期(月),兼容“按月续费”模型 - var months = (effectiveTo.Year - effectiveFrom.Year) * 12 + effectiveTo.Month - effectiveFrom.Month; - - // 2. 对不足 1 个月的情况兜底为 1 - return months <= 0 ? 1 : months; - } - - private static decimal CalculateRenewalAmount(TenantPackage package, int durationMonths) - { - // 1. 优先使用年付价(按整年计费),剩余月份按月付价补齐 - var monthlyPrice = package.MonthlyPrice ?? 0m; - var yearlyPrice = package.YearlyPrice; - if (yearlyPrice is null || durationMonths < 12) - { - return monthlyPrice * durationMonths; - } - - // 2. 按年 + 月组合计算金额 - var years = durationMonths / 12; - var remainingMonths = durationMonths % 12; - return yearlyPrice.Value * years + monthlyPrice * remainingMonths; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/ProcessRenewalRemindersCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/ProcessRenewalRemindersCommandHandler.cs deleted file mode 100644 index f1c1aba..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/ProcessRenewalRemindersCommandHandler.cs +++ /dev/null @@ -1,117 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using System.Text.Json; -using TakeoutSaaS.Application.App.Subscriptions.Commands; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Ids; - -namespace TakeoutSaaS.Application.App.Subscriptions.Handlers; - -/// -/// 续费提醒处理器:在到期前 7/3/1 天等时间点发送站内提醒(幂等)。 -/// -public sealed class ProcessRenewalRemindersCommandHandler( - ISubscriptionRepository subscriptionRepository, - ITenantNotificationRepository notificationRepository, - IIdGenerator idGenerator, - ILogger logger) - : IRequestHandler -{ - private const string ReminderTitle = "订阅续费提醒"; - - /// - public async Task Handle(ProcessRenewalRemindersCommand request, CancellationToken cancellationToken) - { - // 1. 读取提醒配置 - var now = DateTime.UtcNow; - var candidateCount = 0; - var createdReminderCount = 0; - var dedupeWindowStart = now.AddHours(-24); - - // 2. 按提醒时间点扫描到期订阅 - foreach (var daysBeforeExpiry in request.ReminderDaysBeforeExpiry.Distinct().OrderByDescending(x => x)) - { - // 2.1 计算目标日期区间(按天匹配) - var targetDate = now.AddDays(daysBeforeExpiry); - var startOfDay = targetDate.Date; - var endOfDay = startOfDay.AddDays(1); - - // 2.2 查询候选订阅(活跃 + 未开自动续费 + 到期在当日) - var candidates = await subscriptionRepository.FindRenewalReminderCandidatesAsync( - startOfDay, - endOfDay, - cancellationToken); - candidateCount += candidates.Count; - - foreach (var item in candidates) - { - // 2.3 幂等:同一订阅 + 同一天数提醒,在 24 小时内只发送一次 - var metadataJson = BuildReminderMetadata(item.Subscription.Id, daysBeforeExpiry, item.Subscription.EffectiveTo); - var alreadySent = await notificationRepository.ExistsByMetadataAsync( - item.Subscription.TenantId, - ReminderTitle, - metadataJson, - dedupeWindowStart, - cancellationToken); - - if (alreadySent) - { - continue; - } - - // 2.4 构造提醒内容并入库 - var notification = new TenantNotification - { - Id = idGenerator.NextId(), - TenantId = item.Subscription.TenantId, - Title = ReminderTitle, - Message = $"您的订阅套餐「{item.Package.Name}」将在 {daysBeforeExpiry} 天内到期(到期时间:{item.Subscription.EffectiveTo:yyyy-MM-dd HH:mm}),请及时续费以免影响使用。", - Severity = daysBeforeExpiry <= 1 - ? TenantNotificationSeverity.Critical - : TenantNotificationSeverity.Warning, - Channel = TenantNotificationChannel.InApp, - SentAt = now, - ReadAt = null, - MetadataJson = metadataJson, - CreatedAt = now - }; - - await notificationRepository.AddAsync(notification, cancellationToken); - createdReminderCount++; - - logger.LogInformation( - "续费提醒:TenantId={TenantId}, TenantName={TenantName}, SubscriptionId={SubscriptionId}, DaysBeforeExpiry={DaysBeforeExpiry}", - item.Tenant.Id, - item.Tenant.Name, - item.Subscription.Id, - daysBeforeExpiry); - } - } - - // 3. 保存变更 - if (createdReminderCount > 0) - { - await notificationRepository.SaveChangesAsync(cancellationToken); - } - - return new ProcessRenewalRemindersResult - { - CandidateCount = candidateCount, - CreatedReminderCount = createdReminderCount - }; - } - - private static string BuildReminderMetadata(long subscriptionId, int daysBeforeExpiry, DateTime effectiveTo) - { - // 1. 使用稳定字段顺序的 JSON 作为幂等键 - return JsonSerializer.Serialize(new - { - Type = "RenewalReminder", - SubscriptionId = subscriptionId, - DaysBeforeExpiry = daysBeforeExpiry, - EffectiveTo = effectiveTo.ToString("O") - }); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/ProcessSubscriptionExpiryCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/ProcessSubscriptionExpiryCommandHandler.cs deleted file mode 100644 index 9b655e5..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/ProcessSubscriptionExpiryCommandHandler.cs +++ /dev/null @@ -1,63 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Subscriptions.Commands; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; - -namespace TakeoutSaaS.Application.App.Subscriptions.Handlers; - -/// -/// 订阅到期处理器:自动进入宽限期并在宽限期结束后暂停。 -/// -public sealed class ProcessSubscriptionExpiryCommandHandler( - ISubscriptionRepository subscriptionRepository, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(ProcessSubscriptionExpiryCommand request, CancellationToken cancellationToken) - { - // 1. 查询到期订阅 - var now = DateTime.UtcNow; - var expiredActive = await subscriptionRepository.FindExpiredActiveSubscriptionsAsync( - now, - cancellationToken); - var gracePeriodExpired = await subscriptionRepository.FindGracePeriodExpiredSubscriptionsAsync( - now, - request.GracePeriodDays, - cancellationToken); - - // 2. 更新订阅状态 - foreach (var subscription in expiredActive) - { - subscription.Status = SubscriptionStatus.GracePeriod; - await subscriptionRepository.UpdateAsync(subscription, cancellationToken); - } - - // 3. 宽限期到期自动暂停 - foreach (var subscription in gracePeriodExpired) - { - subscription.Status = SubscriptionStatus.Suspended; - await subscriptionRepository.UpdateAsync(subscription, cancellationToken); - } - - // 4. 保存变更 - var totalChanged = expiredActive.Count + gracePeriodExpired.Count; - if (totalChanged > 0) - { - await subscriptionRepository.SaveChangesAsync(cancellationToken); - } - - logger.LogInformation( - "订阅到期处理完成:进入宽限期 {EnteredGracePeriodCount},暂停 {SuspendedCount},宽限期天数 {GracePeriodDays}", - expiredActive.Count, - gracePeriodExpired.Count, - request.GracePeriodDays); - - return new ProcessSubscriptionExpiryResult - { - EnteredGracePeriodCount = expiredActive.Count, - SuspendedCount = gracePeriodExpired.Count - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/UpdateSubscriptionCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/UpdateSubscriptionCommandHandler.cs deleted file mode 100644 index 70c852c..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/UpdateSubscriptionCommandHandler.cs +++ /dev/null @@ -1,48 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Subscriptions.Commands; -using TakeoutSaaS.Application.App.Subscriptions.Dto; -using TakeoutSaaS.Application.App.Subscriptions.Queries; -using TakeoutSaaS.Domain.Tenants.Repositories; - -namespace TakeoutSaaS.Application.App.Subscriptions.Handlers; - -/// -/// 更新订阅基础信息命令处理器。 -/// -public sealed class UpdateSubscriptionCommandHandler( - ISubscriptionRepository subscriptionRepository, - IMediator mediator) - : IRequestHandler -{ - /// - public async Task Handle(UpdateSubscriptionCommand request, CancellationToken cancellationToken) - { - // 1. 查询订阅 - var subscription = await subscriptionRepository.FindByIdAsync( - request.SubscriptionId, - cancellationToken); - - if (subscription == null) - { - return null; - } - - // 2. 更新字段 - if (request.AutoRenew.HasValue) - { - subscription.AutoRenew = request.AutoRenew.Value; - } - - if (request.Notes != null) - { - subscription.Notes = request.Notes; - } - - // 3. 保存更改 - await subscriptionRepository.UpdateAsync(subscription, cancellationToken); - await subscriptionRepository.SaveChangesAsync(cancellationToken); - - // 4. 返回更新后的详情 - return await mediator.Send(new GetSubscriptionDetailQuery { SubscriptionId = subscription.Id }, cancellationToken); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/UpdateSubscriptionStatusCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/UpdateSubscriptionStatusCommandHandler.cs deleted file mode 100644 index 58c2652..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/UpdateSubscriptionStatusCommandHandler.cs +++ /dev/null @@ -1,46 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Subscriptions.Commands; -using TakeoutSaaS.Application.App.Subscriptions.Dto; -using TakeoutSaaS.Application.App.Subscriptions.Queries; -using TakeoutSaaS.Domain.Tenants.Repositories; - -namespace TakeoutSaaS.Application.App.Subscriptions.Handlers; - -/// -/// 更新订阅状态命令处理器。 -/// -public sealed class UpdateSubscriptionStatusCommandHandler( - ISubscriptionRepository subscriptionRepository, - IMediator mediator) - : IRequestHandler -{ - /// - public async Task Handle(UpdateSubscriptionStatusCommand request, CancellationToken cancellationToken) - { - // 1. 查询订阅 - var subscription = await subscriptionRepository.FindByIdAsync( - request.SubscriptionId, - cancellationToken); - - if (subscription == null) - { - return null; - } - - // 2. 更新状态 - subscription.Status = request.Status; - - // 3. 更新备注 - if (!string.IsNullOrWhiteSpace(request.Notes)) - { - subscription.Notes = request.Notes; - } - - // 4. 保存更改 - await subscriptionRepository.UpdateAsync(subscription, cancellationToken); - await subscriptionRepository.SaveChangesAsync(cancellationToken); - - // 5. 返回更新后的详情 - return await mediator.Send(new GetSubscriptionDetailQuery { SubscriptionId = subscription.Id }, cancellationToken); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Queries/GetSubscriptionDetailQuery.cs b/src/Application/TakeoutSaaS.Application/App/Subscriptions/Queries/GetSubscriptionDetailQuery.cs deleted file mode 100644 index c69c3e4..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Queries/GetSubscriptionDetailQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Subscriptions.Dto; - -namespace TakeoutSaaS.Application.App.Subscriptions.Queries; - -/// -/// 查询订阅详情(含套餐信息、配额使用、变更历史)。 -/// -public sealed record GetSubscriptionDetailQuery : IRequest -{ - /// - /// 订阅 ID。 - /// - public long SubscriptionId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Queries/GetSubscriptionListQuery.cs b/src/Application/TakeoutSaaS.Application/App/Subscriptions/Queries/GetSubscriptionListQuery.cs deleted file mode 100644 index e7a8cd4..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Subscriptions/Queries/GetSubscriptionListQuery.cs +++ /dev/null @@ -1,52 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Subscriptions.Dto; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.App.Subscriptions.Queries; - -/// -/// 订阅分页查询。 -/// -public sealed record GetSubscriptionListQuery : IRequest> -{ - /// - /// 订阅状态(精确匹配)。 - /// - public SubscriptionStatus? Status { get; init; } - - /// - /// 套餐 ID(精确匹配)。 - /// - public long? TenantPackageId { get; init; } - - /// - /// 租户 ID(精确匹配)。 - /// - public long? TenantId { get; init; } - - /// - /// 租户关键词(名称或编码模糊匹配)。 - /// - public string? TenantKeyword { get; init; } - - /// - /// 到期时间筛选:未来 N 天内到期。 - /// - public int? ExpiringWithinDays { get; init; } - - /// - /// 是否自动续费筛选。 - /// - public bool? AutoRenew { get; init; } - - /// - /// 页码(从 1 开始)。 - /// - public int Page { get; init; } = 1; - - /// - /// 每页大小。 - /// - public int PageSize { get; init; } = 20; -} diff --git a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Commands/CreateSystemParameterCommand.cs b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Commands/CreateSystemParameterCommand.cs deleted file mode 100644 index c5f332c..0000000 --- a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Commands/CreateSystemParameterCommand.cs +++ /dev/null @@ -1,35 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.SystemParameters.Dto; - -namespace TakeoutSaaS.Application.App.SystemParameters.Commands; - -/// -/// 创建系统参数命令。 -/// -public sealed class CreateSystemParameterCommand : IRequest -{ - /// - /// 参数键。 - /// - public string Key { get; set; } = string.Empty; - - /// - /// 参数值。 - /// - public string Value { get; set; } = string.Empty; - - /// - /// 描述。 - /// - public string? Description { get; set; } - - /// - /// 排序值。 - /// - public int SortOrder { get; set; } = 100; - - /// - /// 是否启用。 - /// - public bool IsEnabled { get; set; } = true; -} diff --git a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Commands/DeleteSystemParameterCommand.cs b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Commands/DeleteSystemParameterCommand.cs deleted file mode 100644 index 6f49ad8..0000000 --- a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Commands/DeleteSystemParameterCommand.cs +++ /dev/null @@ -1,14 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.App.SystemParameters.Commands; - -/// -/// 删除系统参数命令。 -/// -public sealed record DeleteSystemParameterCommand : IRequest -{ - /// - /// 参数 ID。 - /// - public long ParameterId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Commands/UpdateSystemParameterCommand.cs b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Commands/UpdateSystemParameterCommand.cs deleted file mode 100644 index 86bbfa7..0000000 --- a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Commands/UpdateSystemParameterCommand.cs +++ /dev/null @@ -1,40 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.SystemParameters.Dto; - -namespace TakeoutSaaS.Application.App.SystemParameters.Commands; - -/// -/// 更新系统参数命令。 -/// -public sealed record UpdateSystemParameterCommand : IRequest -{ - /// - /// 参数 ID。 - /// - public long ParameterId { get; init; } - - /// - /// 参数键。 - /// - public string Key { get; init; } = string.Empty; - - /// - /// 参数值。 - /// - public string Value { get; init; } = string.Empty; - - /// - /// 描述。 - /// - public string? Description { get; init; } - - /// - /// 排序值。 - /// - public int SortOrder { get; init; } = 100; - - /// - /// 是否启用。 - /// - public bool IsEnabled { get; init; } = true; -} diff --git a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Dto/SystemParameterDto.cs b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Dto/SystemParameterDto.cs deleted file mode 100644 index 8305ae4..0000000 --- a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Dto/SystemParameterDto.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.SystemParameters.Dto; - -/// -/// 系统参数 DTO。 -/// -public sealed class SystemParameterDto -{ - /// - /// 参数 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 租户 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 参数键。 - /// - public string Key { get; init; } = string.Empty; - - /// - /// 参数值。 - /// - public string Value { get; init; } = string.Empty; - - /// - /// 描述。 - /// - public string? Description { get; init; } - - /// - /// 排序值。 - /// - public int SortOrder { get; init; } - - /// - /// 是否启用。 - /// - public bool IsEnabled { get; init; } - - /// - /// 创建时间。 - /// - public DateTime CreatedAt { get; init; } - - /// - /// 最近更新时间。 - /// - public DateTime? UpdatedAt { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/CreateSystemParameterCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/CreateSystemParameterCommandHandler.cs deleted file mode 100644 index 64ab3c1..0000000 --- a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/CreateSystemParameterCommandHandler.cs +++ /dev/null @@ -1,64 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.SystemParameters.Commands; -using TakeoutSaaS.Application.App.SystemParameters.Dto; -using TakeoutSaaS.Domain.SystemParameters.Entities; -using TakeoutSaaS.Domain.SystemParameters.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; - -namespace TakeoutSaaS.Application.App.SystemParameters.Handlers; - -/// -/// 创建系统参数命令处理器。 -/// -public sealed class CreateSystemParameterCommandHandler( - ISystemParameterRepository repository, - ILogger logger) - : IRequestHandler -{ - private readonly ISystemParameterRepository _repository = repository; - private readonly ILogger _logger = logger; - - /// - public async Task Handle(CreateSystemParameterCommand request, CancellationToken cancellationToken) - { - // 1. 唯一性校验 - var existing = await _repository.FindByKeyAsync(request.Key, cancellationToken); - if (existing != null) - { - throw new BusinessException(ErrorCodes.Conflict, "系统参数键已存在"); - } - - // 2. 构建实体 - var parameter = new SystemParameter - { - Key = request.Key.Trim(), - Value = request.Value.Trim(), - Description = request.Description?.Trim(), - SortOrder = request.SortOrder, - IsEnabled = request.IsEnabled - }; - - // 3. 持久化 - await _repository.AddAsync(parameter, cancellationToken); - await _repository.SaveChangesAsync(cancellationToken); - _logger.LogInformation("创建系统参数 {Key}", parameter.Key); - - // 4. 映射返回 - return MapToDto(parameter); - } - - private static SystemParameterDto MapToDto(SystemParameter parameter) => new() - { - Id = parameter.Id, - TenantId = parameter.TenantId, - Key = parameter.Key, - Value = parameter.Value, - Description = parameter.Description, - SortOrder = parameter.SortOrder, - IsEnabled = parameter.IsEnabled, - CreatedAt = parameter.CreatedAt, - UpdatedAt = parameter.UpdatedAt - }; -} diff --git a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/DeleteSystemParameterCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/DeleteSystemParameterCommandHandler.cs deleted file mode 100644 index cda2c42..0000000 --- a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/DeleteSystemParameterCommandHandler.cs +++ /dev/null @@ -1,33 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.SystemParameters.Commands; -using TakeoutSaaS.Domain.SystemParameters.Repositories; - -namespace TakeoutSaaS.Application.App.SystemParameters.Handlers; - -/// -/// 删除系统参数命令处理器。 -/// -public sealed class DeleteSystemParameterCommandHandler( - ISystemParameterRepository repository, - ILogger logger) - : IRequestHandler -{ - private readonly ISystemParameterRepository _repository = repository; - private readonly ILogger _logger = logger; - - /// - public async Task Handle(DeleteSystemParameterCommand request, CancellationToken cancellationToken) - { - var existing = await _repository.FindByIdAsync(request.ParameterId, cancellationToken); - if (existing == null) - { - return false; - } - - await _repository.RemoveAsync(existing, cancellationToken); - await _repository.SaveChangesAsync(cancellationToken); - _logger.LogInformation("删除系统参数 {Key}", existing.Key); - return true; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/GetSystemParameterByIdQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/GetSystemParameterByIdQueryHandler.cs deleted file mode 100644 index c2bc53a..0000000 --- a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/GetSystemParameterByIdQueryHandler.cs +++ /dev/null @@ -1,35 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.SystemParameters.Dto; -using TakeoutSaaS.Application.App.SystemParameters.Queries; -using TakeoutSaaS.Domain.SystemParameters.Repositories; - -namespace TakeoutSaaS.Application.App.SystemParameters.Handlers; - -/// -/// 获取系统参数详情查询处理器。 -/// -public sealed class GetSystemParameterByIdQueryHandler(ISystemParameterRepository repository) - : IRequestHandler -{ - private readonly ISystemParameterRepository _repository = repository; - - /// - public async Task Handle(GetSystemParameterByIdQuery request, CancellationToken cancellationToken) - { - var parameter = await _repository.FindByIdAsync(request.ParameterId, cancellationToken); - return parameter == null ? null : MapToDto(parameter); - } - - private static SystemParameterDto MapToDto(Domain.SystemParameters.Entities.SystemParameter parameter) => new() - { - Id = parameter.Id, - TenantId = parameter.TenantId, - Key = parameter.Key, - Value = parameter.Value, - Description = parameter.Description, - SortOrder = parameter.SortOrder, - IsEnabled = parameter.IsEnabled, - CreatedAt = parameter.CreatedAt, - UpdatedAt = parameter.UpdatedAt - }; -} diff --git a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/SearchSystemParametersQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/SearchSystemParametersQueryHandler.cs deleted file mode 100644 index 678b55c..0000000 --- a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/SearchSystemParametersQueryHandler.cs +++ /dev/null @@ -1,69 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.SystemParameters.Dto; -using TakeoutSaaS.Application.App.SystemParameters.Queries; -using TakeoutSaaS.Domain.SystemParameters.Repositories; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.App.SystemParameters.Handlers; - -/// -/// 系统参数列表查询处理器。 -/// -public sealed class SearchSystemParametersQueryHandler(ISystemParameterRepository repository) - : IRequestHandler> -{ - private readonly ISystemParameterRepository _repository = repository; - - /// - public async Task> Handle(SearchSystemParametersQuery request, CancellationToken cancellationToken) - { - var parameters = await _repository.SearchAsync(request.Keyword, request.IsEnabled, cancellationToken); - - var sorted = ApplySorting(parameters, request.SortBy, request.SortDescending); - var paged = sorted - .Skip((request.Page - 1) * request.PageSize) - .Take(request.PageSize) - .ToList(); - - var items = paged.Select(MapToDto).ToList(); - return new PagedResult(items, request.Page, request.PageSize, parameters.Count); - } - - private static IOrderedEnumerable ApplySorting( - IReadOnlyCollection parameters, - string? sortBy, - bool sortDescending) - { - return sortBy?.ToLowerInvariant() switch - { - "key" => sortDescending - ? parameters.OrderByDescending(x => x.Key) - : parameters.OrderBy(x => x.Key), - "sortorder" => sortDescending - ? parameters.OrderByDescending(x => x.SortOrder) - : parameters.OrderBy(x => x.SortOrder), - "updatedat" => sortDescending - ? parameters.OrderByDescending(x => x.UpdatedAt ?? x.CreatedAt) - : parameters.OrderBy(x => x.UpdatedAt ?? x.CreatedAt), - "isenabled" => sortDescending - ? parameters.OrderByDescending(x => x.IsEnabled) - : parameters.OrderBy(x => x.IsEnabled), - _ => sortDescending - ? parameters.OrderByDescending(x => x.CreatedAt) - : parameters.OrderBy(x => x.CreatedAt) - }; - } - - private static SystemParameterDto MapToDto(Domain.SystemParameters.Entities.SystemParameter parameter) => new() - { - Id = parameter.Id, - TenantId = parameter.TenantId, - Key = parameter.Key, - Value = parameter.Value, - Description = parameter.Description, - SortOrder = parameter.SortOrder, - IsEnabled = parameter.IsEnabled, - CreatedAt = parameter.CreatedAt, - UpdatedAt = parameter.UpdatedAt - }; -} diff --git a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/UpdateSystemParameterCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/UpdateSystemParameterCommandHandler.cs deleted file mode 100644 index 6ba3104..0000000 --- a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/UpdateSystemParameterCommandHandler.cs +++ /dev/null @@ -1,66 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.SystemParameters.Commands; -using TakeoutSaaS.Application.App.SystemParameters.Dto; -using TakeoutSaaS.Domain.SystemParameters.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; - -namespace TakeoutSaaS.Application.App.SystemParameters.Handlers; - -/// -/// 更新系统参数命令处理器。 -/// -public sealed class UpdateSystemParameterCommandHandler( - ISystemParameterRepository repository, - ILogger logger) - : IRequestHandler -{ - private readonly ISystemParameterRepository _repository = repository; - private readonly ILogger _logger = logger; - - /// - public async Task Handle(UpdateSystemParameterCommand request, CancellationToken cancellationToken) - { - // 1. 读取已有参数 - var existing = await _repository.FindByIdAsync(request.ParameterId, cancellationToken); - if (existing == null) - { - return null; - } - - // 2. 唯一性校验 - var duplicate = await _repository.FindByKeyAsync(request.Key, cancellationToken); - if (duplicate != null && duplicate.Id != existing.Id) - { - throw new BusinessException(ErrorCodes.Conflict, "系统参数键已存在"); - } - - // 3. 更新字段 - existing.Key = request.Key.Trim(); - existing.Value = request.Value.Trim(); - existing.Description = request.Description?.Trim(); - existing.SortOrder = request.SortOrder; - existing.IsEnabled = request.IsEnabled; - - // 4. 持久化 - await _repository.UpdateAsync(existing, cancellationToken); - await _repository.SaveChangesAsync(cancellationToken); - _logger.LogInformation("更新系统参数 {Key}", existing.Key); - - return MapToDto(existing); - } - - private static SystemParameterDto MapToDto(Domain.SystemParameters.Entities.SystemParameter parameter) => new() - { - Id = parameter.Id, - TenantId = parameter.TenantId, - Key = parameter.Key, - Value = parameter.Value, - Description = parameter.Description, - SortOrder = parameter.SortOrder, - IsEnabled = parameter.IsEnabled, - CreatedAt = parameter.CreatedAt, - UpdatedAt = parameter.UpdatedAt - }; -} diff --git a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Queries/GetSystemParameterByIdQuery.cs b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Queries/GetSystemParameterByIdQuery.cs deleted file mode 100644 index 09c6b70..0000000 --- a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Queries/GetSystemParameterByIdQuery.cs +++ /dev/null @@ -1,9 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.SystemParameters.Dto; - -namespace TakeoutSaaS.Application.App.SystemParameters.Queries; - -/// -/// 获取系统参数详情查询。 -/// -public sealed record GetSystemParameterByIdQuery(long ParameterId) : IRequest; diff --git a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Queries/SearchSystemParametersQuery.cs b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Queries/SearchSystemParametersQuery.cs deleted file mode 100644 index d6e0238..0000000 --- a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Queries/SearchSystemParametersQuery.cs +++ /dev/null @@ -1,41 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.SystemParameters.Dto; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.App.SystemParameters.Queries; - -/// -/// 系统参数列表查询。 -/// -public sealed class SearchSystemParametersQuery : IRequest> -{ - /// - /// 关键字(匹配 Key/Description)。 - /// - public string? Keyword { get; init; } - - /// - /// 启用状态过滤。 - /// - public bool? IsEnabled { get; init; } - - /// - /// 页码。 - /// - public int Page { get; init; } = 1; - - /// - /// 每页条数。 - /// - public int PageSize { get; init; } = 20; - - /// - /// 排序字段(key/sortOrder/createdAt/updatedAt/isEnabled)。 - /// - public string? SortBy { get; init; } - - /// - /// 是否倒序。 - /// - public bool SortDescending { get; init; } = true; -} diff --git a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Validators/CreateSystemParameterCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Validators/CreateSystemParameterCommandValidator.cs deleted file mode 100644 index a624833..0000000 --- a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Validators/CreateSystemParameterCommandValidator.cs +++ /dev/null @@ -1,21 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.SystemParameters.Commands; - -namespace TakeoutSaaS.Application.App.SystemParameters.Validators; - -/// -/// 创建系统参数命令验证器。 -/// -public sealed class CreateSystemParameterCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public CreateSystemParameterCommandValidator() - { - RuleFor(x => x.Key).NotEmpty().MaximumLength(128); - RuleFor(x => x.Value).NotEmpty(); - RuleFor(x => x.Description).MaximumLength(512); - RuleFor(x => x.SortOrder).GreaterThanOrEqualTo(0); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Validators/SearchSystemParametersQueryValidator.cs b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Validators/SearchSystemParametersQueryValidator.cs deleted file mode 100644 index 83586ab..0000000 --- a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Validators/SearchSystemParametersQueryValidator.cs +++ /dev/null @@ -1,21 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.SystemParameters.Queries; - -namespace TakeoutSaaS.Application.App.SystemParameters.Validators; - -/// -/// 系统参数列表查询验证器。 -/// -public sealed class SearchSystemParametersQueryValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public SearchSystemParametersQueryValidator() - { - RuleFor(x => x.Page).GreaterThan(0); - RuleFor(x => x.PageSize).InclusiveBetween(1, 200); - RuleFor(x => x.Keyword).MaximumLength(256); - RuleFor(x => x.SortBy).MaximumLength(64); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Validators/UpdateSystemParameterCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Validators/UpdateSystemParameterCommandValidator.cs deleted file mode 100644 index 831ad11..0000000 --- a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Validators/UpdateSystemParameterCommandValidator.cs +++ /dev/null @@ -1,22 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.SystemParameters.Commands; - -namespace TakeoutSaaS.Application.App.SystemParameters.Validators; - -/// -/// 更新系统参数命令验证器。 -/// -public sealed class UpdateSystemParameterCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public UpdateSystemParameterCommandValidator() - { - RuleFor(x => x.ParameterId).GreaterThan(0); - RuleFor(x => x.Key).NotEmpty().MaximumLength(128); - RuleFor(x => x.Value).NotEmpty(); - RuleFor(x => x.Description).MaximumLength(512); - RuleFor(x => x.SortOrder).GreaterThanOrEqualTo(0); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/CheckTenantQuotaCommand.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/CheckTenantQuotaCommand.cs deleted file mode 100644 index 3941e81..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/CheckTenantQuotaCommand.cs +++ /dev/null @@ -1,26 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Domain.Tenants.Enums; - -namespace TakeoutSaaS.Application.App.Tenants.Commands; - -/// -/// 校验并消费租户配额命令。 -/// -public sealed record CheckTenantQuotaCommand : IRequest -{ - /// - /// 目标租户 ID。 - /// - public long TenantId { get; init; } - - /// - /// 配额类型。 - /// - public TenantQuotaType QuotaType { get; init; } - - /// - /// 本次申请使用量。 - /// - public decimal Delta { get; init; } = 1; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/CreateTenantAnnouncementCommand.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/CreateTenantAnnouncementCommand.cs deleted file mode 100644 index ad5e471..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/CreateTenantAnnouncementCommand.cs +++ /dev/null @@ -1,67 +0,0 @@ -using MediatR; -using System.ComponentModel.DataAnnotations; -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Domain.Tenants.Enums; - -namespace TakeoutSaaS.Application.App.Tenants.Commands; - -/// -/// 创建租户公告命令。 -/// -public sealed record CreateTenantAnnouncementCommand : IRequest -{ - /// - /// 租户 ID(雪花算法)。 - /// - public long TenantId { get; init; } - - /// - /// 公告标题。 - /// - [Required] - [StringLength(128)] - public string Title { get; init; } = string.Empty; - - /// - /// 公告正文内容。 - /// - [Required] - public string Content { get; init; } = string.Empty; - - /// - /// 公告类型。 - /// - public TenantAnnouncementType AnnouncementType { get; init; } = TenantAnnouncementType.System; - - /// - /// 优先级,数值越大越靠前。 - /// - public int Priority { get; init; } = 0; - - /// - /// 生效开始时间(UTC)。 - /// - public DateTime EffectiveFrom { get; init; } = DateTime.UtcNow; - - /// - /// 生效结束时间(UTC),为空则长期有效。 - /// - public DateTime? EffectiveTo { get; init; } - - /// - /// 发布者范围。 - /// - public PublisherScope PublisherScope { get; init; } = PublisherScope.Tenant; - - /// - /// 目标受众类型。 - /// - [Required] - [MaxLength(64)] - public string TargetType { get; init; } = string.Empty; - - /// - /// 目标受众参数(JSON)。 - /// - public string? TargetParameters { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/DeleteTenantAnnouncementCommand.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/DeleteTenantAnnouncementCommand.cs deleted file mode 100644 index 3cd5964..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/DeleteTenantAnnouncementCommand.cs +++ /dev/null @@ -1,19 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.App.Tenants.Commands; - -/// -/// 删除租户公告命令。 -/// -public sealed record DeleteTenantAnnouncementCommand : IRequest -{ - /// - /// 租户 ID(雪花算法)。 - /// - public long TenantId { get; init; } - - /// - /// 公告 ID。 - /// - public long AnnouncementId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/MarkAnnouncementAsReadCommand.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/MarkAnnouncementAsReadCommand.cs deleted file mode 100644 index 286e207..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/MarkAnnouncementAsReadCommand.cs +++ /dev/null @@ -1,22 +0,0 @@ -using MediatR; -using System.ComponentModel.DataAnnotations; -using TakeoutSaaS.Application.App.Tenants.Dto; - -namespace TakeoutSaaS.Application.App.Tenants.Commands; - -/// -/// 标记公告已读命令。 -/// -public sealed record MarkAnnouncementAsReadCommand : IRequest -{ - /// - /// 租户 ID(雪花算法,兼容旧调用,实际以当前租户为准)。 - /// - public long TenantId { get; init; } - - /// - /// 公告 ID。 - /// - [Range(1, long.MaxValue)] - public long AnnouncementId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/MarkTenantNotificationReadCommand.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/MarkTenantNotificationReadCommand.cs deleted file mode 100644 index 149a74a..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/MarkTenantNotificationReadCommand.cs +++ /dev/null @@ -1,20 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Dto; - -namespace TakeoutSaaS.Application.App.Tenants.Commands; - -/// -/// 标记通知已读命令。 -/// -public sealed record MarkTenantNotificationReadCommand : IRequest -{ - /// - /// 租户 ID(雪花算法)。 - /// - public long TenantId { get; init; } - - /// - /// 通知 ID。 - /// - public long NotificationId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/PublishAnnouncementCommand.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/PublishAnnouncementCommand.cs deleted file mode 100644 index a56c6ba..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/PublishAnnouncementCommand.cs +++ /dev/null @@ -1,24 +0,0 @@ -using MediatR; -using System.ComponentModel.DataAnnotations; -using TakeoutSaaS.Application.App.Tenants.Dto; - -namespace TakeoutSaaS.Application.App.Tenants.Commands; - -/// -/// 发布公告命令。 -/// -public sealed record PublishAnnouncementCommand : IRequest -{ - /// - /// 公告 ID。 - /// - [Range(1, long.MaxValue)] - public long AnnouncementId { get; init; } - - /// - /// 并发控制版本。 - /// - [Required] - [MinLength(1)] - public byte[] RowVersion { get; init; } = Array.Empty(); -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/RevokeAnnouncementCommand.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/RevokeAnnouncementCommand.cs deleted file mode 100644 index fc5628d..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/RevokeAnnouncementCommand.cs +++ /dev/null @@ -1,24 +0,0 @@ -using MediatR; -using System.ComponentModel.DataAnnotations; -using TakeoutSaaS.Application.App.Tenants.Dto; - -namespace TakeoutSaaS.Application.App.Tenants.Commands; - -/// -/// 撤销公告命令。 -/// -public sealed record RevokeAnnouncementCommand : IRequest -{ - /// - /// 公告 ID。 - /// - [Range(1, long.MaxValue)] - public long AnnouncementId { get; init; } - - /// - /// 并发控制版本。 - /// - [Required] - [MinLength(1)] - public byte[] RowVersion { get; init; } = Array.Empty(); -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/SelfRegisterTenantCommand.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/SelfRegisterTenantCommand.cs deleted file mode 100644 index cddd7ed..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/SelfRegisterTenantCommand.cs +++ /dev/null @@ -1,46 +0,0 @@ -using MediatR; -using System.ComponentModel.DataAnnotations; -using TakeoutSaaS.Application.App.Tenants.Dto; - -namespace TakeoutSaaS.Application.App.Tenants.Commands; - -/// -/// 自助注册租户命令。 -/// -public sealed record SelfRegisterTenantCommand : IRequest -{ - /// - /// 初始管理员账号。 - /// - [Required] - [StringLength(64)] - [RegularExpression("^[A-Za-z0-9]+$", ErrorMessage = "登录账号仅允许大小写字母和数字")] - public string AdminAccount { get; init; } = string.Empty; - - /// - /// 初始管理员展示名称。 - /// - [StringLength(64)] - public string? AdminDisplayName { get; init; } - - /// - /// 初始管理员邮箱。 - /// - [EmailAddress] - [StringLength(128)] - public string? AdminEmail { get; init; } - - /// - /// 初始管理员手机号。 - /// - [Required] - [StringLength(32)] - public string AdminPhone { get; init; } = string.Empty; - - /// - /// 初始管理员登录密码(前端自定义)。 - /// - [Required] - [StringLength(128, MinimumLength = 8)] - public string AdminPassword { get; init; } = string.Empty; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/SubmitTenantVerificationCommand.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/SubmitTenantVerificationCommand.cs deleted file mode 100644 index 94de46d..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/SubmitTenantVerificationCommand.cs +++ /dev/null @@ -1,67 +0,0 @@ -using MediatR; -using System.ComponentModel.DataAnnotations; -using TakeoutSaaS.Application.App.Tenants.Dto; - -namespace TakeoutSaaS.Application.App.Tenants.Commands; - -/// -/// 提交租户实名认证资料。 -/// -public sealed record SubmitTenantVerificationCommand : IRequest -{ - /// - /// 租户 ID(雪花算法)。 - /// - [Required] - public long TenantId { get; init; } - - /// - /// 营业执照编号。 - /// - public string? BusinessLicenseNumber { get; init; } - - /// - /// 营业执照扫描件地址。 - /// - public string? BusinessLicenseUrl { get; init; } - - /// - /// 法人姓名。 - /// - public string? LegalPersonName { get; init; } - - /// - /// 法人身份证号。 - /// - public string? LegalPersonIdNumber { get; init; } - - /// - /// 法人身份证人像面图片地址。 - /// - public string? LegalPersonIdFrontUrl { get; init; } - - /// - /// 法人身份证国徽面图片地址。 - /// - public string? LegalPersonIdBackUrl { get; init; } - - /// - /// 对公账户户名。 - /// - public string? BankAccountName { get; init; } - - /// - /// 对公银行账号。 - /// - public string? BankAccountNumber { get; init; } - - /// - /// 开户行名称。 - /// - public string? BankName { get; init; } - - /// - /// 其他补充资料 JSON。 - /// - public string? AdditionalDataJson { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/UpdateTenantAnnouncementCommand.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/UpdateTenantAnnouncementCommand.cs deleted file mode 100644 index 9ff5291..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/UpdateTenantAnnouncementCommand.cs +++ /dev/null @@ -1,53 +0,0 @@ -using MediatR; -using System.ComponentModel.DataAnnotations; -using TakeoutSaaS.Application.App.Tenants.Dto; - -namespace TakeoutSaaS.Application.App.Tenants.Commands; - -/// -/// 更新租户公告命令。 -/// -public sealed record UpdateTenantAnnouncementCommand : IRequest -{ - /// - /// 租户 ID(雪花算法)。 - /// - public long TenantId { get; init; } - - /// - /// 公告 ID。 - /// - public long AnnouncementId { get; init; } - - /// - /// 公告标题。 - /// - [Required] - [StringLength(128)] - public string Title { get; init; } = string.Empty; - - /// - /// 公告内容。 - /// - [Required] - public string Content { get; init; } = string.Empty; - - /// - /// 目标受众类型。 - /// - [Required] - [MaxLength(64)] - public string TargetType { get; init; } = string.Empty; - - /// - /// 目标受众参数(JSON)。 - /// - public string? TargetParameters { get; init; } - - /// - /// 并发控制版本。 - /// - [Required] - [MinLength(1)] - public byte[] RowVersion { get; init; } = Array.Empty(); -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/UpdateTenantCommand.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/UpdateTenantCommand.cs deleted file mode 100644 index dcc5cda..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/UpdateTenantCommand.cs +++ /dev/null @@ -1,53 +0,0 @@ -using MediatR; -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Application.App.Tenants.Commands; - -/// -/// 更新租户基础信息命令。 -/// -public sealed record UpdateTenantCommand : IRequest -{ - /// - /// 租户 ID(雪花算法)。 - /// - public long TenantId { get; init; } - - /// - /// 租户名称。 - /// - [Required] - [StringLength(128)] - public string Name { get; init; } = string.Empty; - - /// - /// 租户简称。 - /// - [StringLength(64)] - public string? ShortName { get; init; } - - /// - /// 所属行业。 - /// - [StringLength(64)] - public string? Industry { get; init; } - - /// - /// 联系人姓名。 - /// - [StringLength(64)] - public string? ContactName { get; init; } - - /// - /// 联系人电话。 - /// - [StringLength(32)] - public string? ContactPhone { get; init; } - - /// - /// 联系人邮箱。 - /// - [StringLength(128)] - public string? ContactEmail { get; init; } -} - diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/QuotaCheckResultDto.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/QuotaCheckResultDto.cs deleted file mode 100644 index b9ce7e6..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/QuotaCheckResultDto.cs +++ /dev/null @@ -1,29 +0,0 @@ -using TakeoutSaaS.Domain.Tenants.Enums; - -namespace TakeoutSaaS.Application.App.Tenants.Dto; - -/// -/// 配额校验结果。 -/// -public sealed class QuotaCheckResultDto -{ - /// - /// 配额类型。 - /// - public TenantQuotaType QuotaType { get; init; } - - /// - /// 当前配额上限,null 表示无限制。 - /// - public decimal? Limit { get; init; } - - /// - /// 已使用数量。 - /// - public decimal Used { get; init; } - - /// - /// 剩余额度,null 表示无限制。 - /// - public decimal? Remaining { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/QuotaUsageHistoryDto.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/QuotaUsageHistoryDto.cs deleted file mode 100644 index bff6e51..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/QuotaUsageHistoryDto.cs +++ /dev/null @@ -1,45 +0,0 @@ -using TakeoutSaaS.Domain.Tenants.Enums; - -namespace TakeoutSaaS.Application.App.Tenants.Dto; - -/// -/// 租户配额使用历史 DTO。 -/// -public sealed record QuotaUsageHistoryDto -{ - /// - /// 配额类型。 - /// - public TenantQuotaType QuotaType { get; init; } - - /// - /// 已使用值。 - /// - public decimal UsedValue { get; init; } - - /// - /// 限额值。 - /// - public decimal LimitValue { get; init; } - - /// - /// 记录时间(UTC)。 - /// - public DateTime RecordedAt { get; init; } - - /// - /// 变更类型:increase | decrease | init | snapshot。 - /// - public string ChangeType { get; init; } = "snapshot"; - - /// - /// 变更量(可选)。 - /// - public decimal? ChangeAmount { get; init; } - - /// - /// 变更原因(可选)。 - /// - public string? ChangeReason { get; init; } -} - diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/SelfRegisterResultDto.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/SelfRegisterResultDto.cs deleted file mode 100644 index 024e485..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/SelfRegisterResultDto.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Tenants.Dto; - -/// -/// 自助注册结果 DTO。 -/// -public sealed class SelfRegisterResultDto -{ - /// - /// 租户 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 租户编码。 - /// - public string Code { get; init; } = string.Empty; - - /// - /// 初始状态。 - /// - public TenantStatus Status { get; init; } = TenantStatus.PendingReview; - - /// - /// 当前实名状态。 - /// - public TenantVerificationStatus VerificationStatus { get; init; } = TenantVerificationStatus.Draft; - - /// - /// 订阅开始时间。 - /// - public DateTime? EffectiveFrom { get; init; } - - /// - /// 订阅到期时间。 - /// - public DateTime? EffectiveTo { get; init; } - - /// - /// 初始管理员账号。 - /// - public string AdminAccount { get; init; } = string.Empty; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantAnnouncementDto.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantAnnouncementDto.cs deleted file mode 100644 index 369d85a..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantAnnouncementDto.cs +++ /dev/null @@ -1,113 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Tenants.Dto; - -/// -/// 租户公告 DTO。 -/// -public sealed class TenantAnnouncementDto -{ - /// - /// 公告 ID(雪花算法,序列化为字符串)。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 租户 ID(雪花算法,序列化为字符串)。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 公告标题。 - /// - public string Title { get; init; } = string.Empty; - - /// - /// 公告正文内容。 - /// - public string Content { get; init; } = string.Empty; - - /// - /// 公告类型。 - /// - public TenantAnnouncementType AnnouncementType { get; init; } - - /// - /// 优先级,数值越大越靠前。 - /// - public int Priority { get; init; } - - /// - /// 生效开始时间(UTC)。 - /// - public DateTime EffectiveFrom { get; init; } - - /// - /// 生效结束时间(UTC),为空则长期有效。 - /// - public DateTime? EffectiveTo { get; init; } - - /// - /// 发布者范围。 - /// - public PublisherScope PublisherScope { get; init; } - - /// - /// 发布者用户 ID。 - /// - public long? PublisherUserId { get; init; } - - /// - /// 公告状态。 - /// - public AnnouncementStatus Status { get; init; } - - /// - /// 实际发布时间(UTC)。 - /// - public DateTime? PublishedAt { get; init; } - - /// - /// 撤销时间(UTC)。 - /// - public DateTime? RevokedAt { get; init; } - - /// - /// 预定发布时间(UTC)。 - /// - public DateTime? ScheduledPublishAt { get; init; } - - /// - /// 目标受众类型。 - /// - public string TargetType { get; init; } = string.Empty; - - /// - /// 目标受众参数(JSON)。 - /// - public string? TargetParameters { get; init; } - - /// - /// 并发控制版本。 - /// - public byte[] RowVersion { get; init; } = Array.Empty(); - - /// - /// 是否启用(迁移期保留)。 - /// - public bool IsActive { get; init; } - - /// - /// 当前用户是否已读。 - /// - public bool IsRead { get; init; } - - /// - /// 已读时间(UTC)。 - /// - public DateTime? ReadAt { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantBillingDto.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantBillingDto.cs deleted file mode 100644 index 1007224..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantBillingDto.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Tenants.Dto; - -/// -/// 租户账单 DTO。 -/// -public sealed class TenantBillingDto -{ - /// - /// 账单 ID(雪花算法,序列化为字符串)。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 租户 ID(雪花算法,序列化为字符串)。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 账单编号。 - /// - public string StatementNo { get; init; } = string.Empty; - - /// - /// 计费周期开始时间(UTC)。 - /// - public DateTime PeriodStart { get; init; } - - /// - /// 计费周期结束时间(UTC)。 - /// - public DateTime PeriodEnd { get; init; } - - /// - /// 应付金额。 - /// - public decimal AmountDue { get; init; } - - /// - /// 已付金额。 - /// - public decimal AmountPaid { get; init; } - - /// - /// 账单状态。 - /// - public TenantBillingStatus Status { get; init; } - - /// - /// 到期日(UTC)。 - /// - public DateTime DueDate { get; init; } - - /// - /// 账单明细 JSON。 - /// - public string? LineItemsJson { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantNotificationDto.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantNotificationDto.cs deleted file mode 100644 index 9a33244..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantNotificationDto.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Tenants.Dto; - -/// -/// 租户通知 DTO。 -/// -public sealed class TenantNotificationDto -{ - /// - /// 通知 ID(雪花算法,序列化为字符串)。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 租户 ID(雪花算法,序列化为字符串)。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 通知标题。 - /// - public string Title { get; init; } = string.Empty; - - /// - /// 通知内容。 - /// - public string Message { get; init; } = string.Empty; - - /// - /// 通道类型(如站内信、短信、邮件)。 - /// - public TenantNotificationChannel Channel { get; init; } - - /// - /// 通知等级。 - /// - public TenantNotificationSeverity Severity { get; init; } - - /// - /// 发送时间(UTC)。 - /// - public DateTime SentAt { get; init; } - - /// - /// 阅读时间(UTC)。 - /// - public DateTime? ReadAt { get; init; } - - /// - /// 附加元数据 JSON。 - /// - public string? MetadataJson { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantPackageDto.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantPackageDto.cs deleted file mode 100644 index a3752c7..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantPackageDto.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Tenants.Dto; - -/// -/// 租户套餐 DTO。 -/// -public sealed class TenantPackageDto -{ - /// - /// 套餐 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 套餐名称。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 描述。 - /// - public string? Description { get; init; } - - /// - /// 套餐类型。 - /// - public TenantPackageType PackageType { get; init; } - - /// - /// 月付价格。 - /// - public decimal? MonthlyPrice { get; init; } - - /// - /// 年付价格。 - /// - public decimal? YearlyPrice { get; init; } - - /// - /// 最大门店数。 - /// - public int? MaxStoreCount { get; init; } - - /// - /// 最大账号数。 - /// - public int? MaxAccountCount { get; init; } - - /// - /// 存储上限(GB)。 - /// - public int? MaxStorageGb { get; init; } - - /// - /// 短信额度。 - /// - public int? MaxSmsCredits { get; init; } - - /// - /// 配送单上限。 - /// - public int? MaxDeliveryOrders { get; init; } - - /// - /// 权益明细 JSON。 - /// - public string? FeaturePoliciesJson { get; init; } - - /// - /// 是否仍启用(系统控制)。 - /// - public bool IsActive { get; init; } - - /// - /// 是否对外可见。 - /// - public bool IsPublicVisible { get; init; } - - /// - /// 是否允许新租户购买/选择。 - /// - public bool IsAllowNewTenantPurchase { get; init; } - - /// - /// 发布状态。 - /// - public TenantPackagePublishStatus PublishStatus { get; init; } - - /// - /// 是否推荐展示(运营推荐标识)。 - /// - public bool IsRecommended { get; init; } - - /// - /// 套餐标签(用于展示与对比页)。 - /// - public string[] Tags { get; init; } = []; - - /// - /// 展示排序,数值越小越靠前。 - /// - public int SortOrder { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantProgressDto.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantProgressDto.cs deleted file mode 100644 index 25e5807..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantProgressDto.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Tenants.Dto; - -/// -/// 租户入住进度 DTO。 -/// -public sealed class TenantProgressDto -{ - /// - /// 租户 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 租户编码。 - /// - public string Code { get; init; } = string.Empty; - - /// - /// 当前租户状态。 - /// - public TenantStatus Status { get; init; } - - /// - /// 实名审核状态。 - /// - public TenantVerificationStatus VerificationStatus { get; init; } - - /// - /// 当前订阅开始时间。 - /// - public DateTime? EffectiveFrom { get; init; } - - /// - /// 当前订阅到期时间。 - /// - public DateTime? EffectiveTo { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantVerificationDto.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantVerificationDto.cs deleted file mode 100644 index f925008..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantVerificationDto.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.App.Tenants.Dto; - -/// -/// 租户实名认证 DTO。 -/// -public sealed class TenantVerificationDto -{ - /// - /// 主键。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 租户标识。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 状态。 - /// - public TenantVerificationStatus Status { get; init; } - - /// - /// 营业执照号。 - /// - public string? BusinessLicenseNumber { get; init; } - - /// - /// 营业执照图片。 - /// - public string? BusinessLicenseUrl { get; init; } - - /// - /// 法人姓名。 - /// - public string? LegalPersonName { get; init; } - - /// - /// 法人身份证号。 - /// - public string? LegalPersonIdNumber { get; init; } - - /// - /// 法人身份证正面。 - /// - public string? LegalPersonIdFrontUrl { get; init; } - - /// - /// 法人身份证反面。 - /// - public string? LegalPersonIdBackUrl { get; init; } - - /// - /// 开户名。 - /// - public string? BankAccountName { get; init; } - - /// - /// 银行账号。 - /// - public string? BankAccountNumber { get; init; } - - /// - /// 银行名称。 - /// - public string? BankName { get; init; } - - /// - /// 附加资料(JSON)。 - /// - public string? AdditionalDataJson { get; init; } - - /// - /// 提交时间。 - /// - public DateTime? SubmittedAt { get; init; } - - /// - /// 审核人 ID。 - /// - [JsonConverter(typeof(NullableSnowflakeIdJsonConverter))] - public long? ReviewedBy { get; init; } - - /// - /// 审核备注。 - /// - public string? ReviewRemarks { get; init; } - - /// - /// 最新审核人。 - /// - public string? ReviewedByName { get; init; } - - /// - /// 审核时间。 - /// - public DateTime? ReviewedAt { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/CheckTenantQuotaCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/CheckTenantQuotaCommandHandler.cs deleted file mode 100644 index 496d331..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/CheckTenantQuotaCommandHandler.cs +++ /dev/null @@ -1,162 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Commands; -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Tenants.Handlers; - -/// -/// 配额校验处理器。 -/// -public sealed class CheckTenantQuotaCommandHandler( - ITenantRepository tenantRepository, - ITenantPackageRepository packageRepository, - ITenantQuotaUsageRepository quotaUsageRepository, - ITenantQuotaUsageHistoryRepository quotaUsageHistoryRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - public async Task Handle(CheckTenantQuotaCommand request, CancellationToken cancellationToken) - { - // 1. 校验请求参数 - if (request.Delta <= 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "配额消耗量必须大于 0"); - } - - // 2. 校验租户上下文 - var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (currentTenantId == 0 || currentTenantId != request.TenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "租户上下文不匹配,请在请求头 X-Tenant-Id 指定目标租户"); - } - - // 3. 获取租户与当前订阅 - _ = await tenantRepository.FindByIdAsync(request.TenantId, cancellationToken) - ?? throw new BusinessException(ErrorCodes.NotFound, "租户不存在"); - - var subscription = await tenantRepository.GetActiveSubscriptionAsync(request.TenantId, cancellationToken); - if (subscription == null || subscription.EffectiveTo <= DateTime.UtcNow) - { - throw new BusinessException(ErrorCodes.Conflict, "订阅不存在或已到期"); - } - - var package = await packageRepository.FindByIdAsync(subscription.TenantPackageId, cancellationToken) - ?? throw new BusinessException(ErrorCodes.NotFound, "套餐不存在"); - - var limit = ResolveLimit(package, request.QuotaType); - - // 4. 加载配额使用记录并计算 - var usage = await quotaUsageRepository.FindAsync(request.TenantId, request.QuotaType, cancellationToken) - ?? new TenantQuotaUsage - { - TenantId = request.TenantId, - QuotaType = request.QuotaType, - LimitValue = limit ?? 0, - UsedValue = 0, - ResetCycle = ResolveResetCycle(request.QuotaType) - }; - - // 4.1 记录是否为首次初始化(用于落库历史) - var isNewUsage = usage.Id == 0; - - var usedAfter = usage.UsedValue + request.Delta; - if (limit.HasValue && usedAfter > (decimal)limit.Value) - { - usage.LimitValue = limit.Value; - await PersistUsageAsync(usage, quotaUsageRepository, cancellationToken); - throw new BusinessException(ErrorCodes.Conflict, $"{request.QuotaType} 配额不足"); - } - - // 5. 更新使用并保存 - usage.LimitValue = limit ?? usage.LimitValue; - usage.UsedValue = usedAfter; - usage.ResetCycle ??= ResolveResetCycle(request.QuotaType); - - // 5.1 落库历史(初始化 + 本次消耗) - var now = DateTime.UtcNow; - if (isNewUsage) - { - await quotaUsageHistoryRepository.AddAsync(new TenantQuotaUsageHistory - { - TenantId = request.TenantId, - QuotaType = request.QuotaType, - UsedValue = 0, - LimitValue = usage.LimitValue, - RecordedAt = now, - ChangeType = TenantQuotaUsageHistoryChangeType.Init, - ChangeReason = "初始化配额使用记录" - }, cancellationToken); - } - - await quotaUsageHistoryRepository.AddAsync(new TenantQuotaUsageHistory - { - TenantId = request.TenantId, - QuotaType = request.QuotaType, - UsedValue = usage.UsedValue, - LimitValue = usage.LimitValue, - RecordedAt = now, - ChangeType = TenantQuotaUsageHistoryChangeType.Decrease, - ChangeAmount = request.Delta, - ChangeReason = "消耗配额" - }, cancellationToken); - - await PersistUsageAsync(usage, quotaUsageRepository, cancellationToken); - - // 6. 返回结果 - return new QuotaCheckResultDto - { - QuotaType = request.QuotaType, - Limit = limit, - Used = usage.UsedValue, - Remaining = limit.HasValue ? limit.Value - usage.UsedValue : null - }; - } - - private static decimal? ResolveLimit(TenantPackage package, TenantQuotaType quotaType) - { - return quotaType switch - { - TenantQuotaType.StoreCount => package.MaxStoreCount, - TenantQuotaType.AccountCount => package.MaxAccountCount, - TenantQuotaType.Storage => package.MaxStorageGb, - TenantQuotaType.SmsCredits => package.MaxSmsCredits, - TenantQuotaType.DeliveryOrders => package.MaxDeliveryOrders, - _ => null - }; - } - - private static string ResolveResetCycle(TenantQuotaType quotaType) - { - return quotaType switch - { - TenantQuotaType.SmsCredits => "monthly", - TenantQuotaType.DeliveryOrders => "monthly", - _ => "lifetime" - }; - } - - private static async Task PersistUsageAsync( - TenantQuotaUsage usage, - ITenantQuotaUsageRepository quotaUsageRepository, - CancellationToken cancellationToken) - { - // 判断是否为新增。 - if (usage.Id == 0) - { - await quotaUsageRepository.AddAsync(usage, cancellationToken); - } - else - { - await quotaUsageRepository.UpdateAsync(usage, cancellationToken); - } - - await quotaUsageRepository.SaveChangesAsync(cancellationToken); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/CreateTenantAnnouncementCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/CreateTenantAnnouncementCommandHandler.cs deleted file mode 100644 index e45843c..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/CreateTenantAnnouncementCommandHandler.cs +++ /dev/null @@ -1,99 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Commands; -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Application.App.Tenants.Targeting; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Tenants.Handlers; - -/// -/// 创建公告处理器。 -/// -public sealed class CreateTenantAnnouncementCommandHandler( - ITenantAnnouncementRepository announcementRepository, - ITenantProvider tenantProvider, - ICurrentUserAccessor currentUserAccessor) - : IRequestHandler -{ - /// - /// 处理创建租户公告请求。 - /// - /// 创建命令。 - /// 取消标记。 - /// 公告 DTO。 - public async Task Handle(CreateTenantAnnouncementCommand request, CancellationToken cancellationToken) - { - // 1. 校验租户上下文(租户端禁止跨租户/系统公告) - var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (currentTenantId <= 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识"); - } - - // 2. (空行后) 兼容旧调用:若传入 TenantId,则必须与当前租户一致 - if (request.TenantId > 0 && request.TenantId != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "无权创建其他租户公告"); - } - - // 3. (空行后) 校验标题与内容 - if (string.IsNullOrWhiteSpace(request.Title) || string.IsNullOrWhiteSpace(request.Content)) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "公告标题和内容不能为空"); - } - - // 4. (空行后) 校验公告发布范围:租户端仅允许租户公告 - if (request.PublisherScope != PublisherScope.Tenant) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "租户端仅允许创建租户公告"); - } - - if (string.IsNullOrWhiteSpace(request.TargetType)) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "目标受众类型不能为空"); - } - // 4.1 (空行后) 校验目标受众类型:租户端禁止跨租户目标类型 - if (!TenantAnnouncementTargetTypePolicy.IsAllowed(request.TargetType)) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "租户端不支持该目标受众类型"); - } - - if (request.EffectiveTo.HasValue && request.EffectiveFrom >= request.EffectiveTo.Value) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "生效开始时间必须早于结束时间"); - } - - // 5. (空行后) 构建公告实体 - var tenantId = currentTenantId; - var publisherUserId = currentUserAccessor.UserId == 0 ? (long?)null : currentUserAccessor.UserId; - // 5.1 (空行后) 规范化目标类型,避免写入脏数据 - var normalizedTargetType = TenantAnnouncementTargetTypePolicy.Normalize(request.TargetType); - var announcement = new TenantAnnouncement - { - TenantId = tenantId, - Title = request.Title.Trim(), - Content = request.Content, - AnnouncementType = request.AnnouncementType, - Priority = request.Priority, - EffectiveFrom = request.EffectiveFrom, - EffectiveTo = request.EffectiveTo, - PublisherScope = request.PublisherScope, - PublisherUserId = publisherUserId, - Status = AnnouncementStatus.Draft, - TargetType = normalizedTargetType, - TargetParameters = request.TargetParameters - }; - - // 6. (空行后) 持久化并返回 DTO - await announcementRepository.AddAsync(announcement, cancellationToken); - await announcementRepository.SaveChangesAsync(cancellationToken); - - return announcement.ToDto(false, null); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/DeleteTenantAnnouncementCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/DeleteTenantAnnouncementCommandHandler.cs deleted file mode 100644 index e175625..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/DeleteTenantAnnouncementCommandHandler.cs +++ /dev/null @@ -1,46 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Commands; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Tenants.Handlers; - -/// -/// 删除公告处理器。 -/// -public sealed class DeleteTenantAnnouncementCommandHandler( - ITenantAnnouncementRepository announcementRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - /// 处理删除公告请求。 - /// - /// 删除命令。 - /// 取消标记。 - /// 执行结果。 - public async Task Handle(DeleteTenantAnnouncementCommand request, CancellationToken cancellationToken) - { - // 1. 校验租户上下文(租户端禁止跨租户) - var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (currentTenantId <= 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识"); - } - - // 2. (空行后) 兼容旧调用:若传入 TenantId,则必须与当前租户一致 - if (request.TenantId > 0 && request.TenantId != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "无权删除其他租户公告"); - } - - // 3. (空行后) 删除公告 - await announcementRepository.DeleteAsync(currentTenantId, request.AnnouncementId, cancellationToken); - await announcementRepository.SaveChangesAsync(cancellationToken); - - // 4. (空行后) 返回执行结果 - return true; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetAnnouncementByIdQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetAnnouncementByIdQueryHandler.cs deleted file mode 100644 index ac7c4dd..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetAnnouncementByIdQueryHandler.cs +++ /dev/null @@ -1,71 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Application.App.Tenants.Queries; -using TakeoutSaaS.Application.App.Tenants.Targeting; -using TakeoutSaaS.Application.Identity.Abstractions; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Tenants.Handlers; - -/// -/// 公告详情查询处理器。 -/// -public sealed class GetAnnouncementByIdQueryHandler( - ITenantAnnouncementRepository announcementRepository, - ITenantAnnouncementReadRepository readRepository, - ITenantProvider tenantProvider, - ICurrentUserAccessor? currentUserAccessor = null, - IAdminAuthService? adminAuthService = null, - IMiniAuthService? miniAuthService = null) - : IRequestHandler -{ - /// - /// 查询公告详情。 - /// - /// 查询请求。 - /// 取消标记。 - /// 公告 DTO 或 null。 - public async Task Handle(GetAnnouncementByIdQuery request, CancellationToken cancellationToken) - { - var tenantId = tenantProvider.GetCurrentTenantId(); - - // 1. 查询公告主体 - var announcement = await announcementRepository.FindByIdAsync(tenantId, request.AnnouncementId, cancellationToken); - if (announcement == null) - { - return null; - } - - // 2. 目标受众过滤 - var targetContext = await AnnouncementTargetContextFactory.BuildAsync( - tenantProvider, - currentUserAccessor, - adminAuthService, - miniAuthService, - cancellationToken); - - if (!TargetTypeFilter.IsMatch(announcement, targetContext)) - { - return null; - } - - // 3. 优先查用户级已读 - var userId = targetContext.UserId; - var reads = await readRepository.GetByAnnouncementAsync( - tenantId, - new[] { announcement.Id }, - userId == 0 ? null : userId, - cancellationToken); - - if (reads.Count == 0) - { - var tenantReads = await readRepository.GetByAnnouncementAsync(tenantId, new[] { announcement.Id }, null, cancellationToken); - reads = tenantReads; - } - - var readRecord = reads.FirstOrDefault(); - return announcement.ToDto(readRecord != null, readRecord?.ReadAt); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetPublicTenantPackagesQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetPublicTenantPackagesQueryHandler.cs deleted file mode 100644 index a974f4c..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetPublicTenantPackagesQueryHandler.cs +++ /dev/null @@ -1,36 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Application.App.Tenants.Queries; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.App.Tenants.Handlers; - -/// -/// 公共场景分页查询启用套餐处理器。 -/// -public sealed class GetPublicTenantPackagesQueryHandler(ITenantPackageRepository packageRepository) - : IRequestHandler> -{ - /// - public async Task> Handle(GetPublicTenantPackagesQuery request, CancellationToken cancellationToken) - { - // 1. 仅查询公共可选购套餐(已发布 + 对外可见 + 允许新购 + 启用) - var packages = await packageRepository.SearchPublicPurchasableAsync(cancellationToken); - // 2. 规范化分页参数 - var pageIndex = request.Page <= 0 ? 1 : request.Page; - var size = request.PageSize <= 0 ? 20 : request.PageSize; - // 3. 执行排序、分页与映射 - var ordered = packages - .OrderBy(x => x.SortOrder) - .ThenByDescending(x => x.CreatedAt) - .ToList(); - var items = ordered - .Skip((pageIndex - 1) * size) - .Take(size) - .Select(x => x.ToDto()) - .ToList(); - // 4. 返回分页结果 - return new PagedResult(items, pageIndex, size, ordered.Count); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetTenantBillQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetTenantBillQueryHandler.cs deleted file mode 100644 index c6b7c50..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetTenantBillQueryHandler.cs +++ /dev/null @@ -1,46 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Application.App.Tenants.Queries; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Tenants.Handlers; - -/// -/// 账单详情查询处理器。 -/// -public sealed class GetTenantBillQueryHandler( - ITenantBillingRepository billingRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - /// 查询账单详情。 - /// - /// 查询请求。 - /// 取消标记。 - /// 账单 DTO 或 null。 - public async Task Handle(GetTenantBillQuery request, CancellationToken cancellationToken) - { - // 1. 校验租户上下文(租户端禁止跨租户) - var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (currentTenantId <= 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识"); - } - - // 2. (空行后) 兼容旧调用:若传入 TenantId,则必须与当前租户一致 - if (request.TenantId > 0 && request.TenantId != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "无权查询其他租户账单"); - } - - // 3. (空行后) 查询账单 - var bill = await billingRepository.FindByIdAsync(currentTenantId, request.BillingId, cancellationToken); - - // 4. (空行后) 返回 DTO 或 null - return bill?.ToDto(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetTenantPackageByIdQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetTenantPackageByIdQueryHandler.cs deleted file mode 100644 index 4b6b898..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetTenantPackageByIdQueryHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Application.App.Tenants.Queries; -using TakeoutSaaS.Domain.Tenants.Repositories; - -namespace TakeoutSaaS.Application.App.Tenants.Handlers; - -/// -/// 套餐详情查询处理器。 -/// -public sealed class GetTenantPackageByIdQueryHandler(ITenantPackageRepository packageRepository) - : IRequestHandler -{ - /// - public async Task Handle(GetTenantPackageByIdQuery request, CancellationToken cancellationToken) - { - // 1. 查询套餐 - var package = await packageRepository.FindByIdAsync(request.TenantPackageId, cancellationToken); - - // 2. 返回 DTO 或 null - return package?.ToDto(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetTenantProgressQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetTenantProgressQueryHandler.cs deleted file mode 100644 index efe1cbe..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetTenantProgressQueryHandler.cs +++ /dev/null @@ -1,55 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Application.App.Tenants.Queries; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Tenants.Handlers; - -/// -/// 租户入住进度查询处理器。 -/// -public sealed class GetTenantProgressQueryHandler( - ITenantRepository tenantRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - public async Task Handle(GetTenantProgressQuery request, CancellationToken cancellationToken) - { - // 1. 校验租户上下文(租户端禁止跨租户) - var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (currentTenantId <= 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识"); - } - - // 2. (空行后) 兼容旧调用:若传入 TenantId,则必须与当前租户一致 - if (request.TenantId > 0 && request.TenantId != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "无权查询其他租户进度"); - } - - // 3. (空行后) 查询租户 - var tenant = await tenantRepository.FindByIdAsync(currentTenantId, cancellationToken) - ?? throw new BusinessException(ErrorCodes.NotFound, "租户不存在"); - - // 4. (空行后) 查询订阅与实名 - var subscription = await tenantRepository.GetActiveSubscriptionAsync(currentTenantId, cancellationToken); - var verification = await tenantRepository.GetVerificationProfileAsync(currentTenantId, cancellationToken); - - // 5. (空行后) 组装进度信息 - return new TenantProgressDto - { - TenantId = tenant.Id, - Code = tenant.Code, - Status = tenant.Status, - VerificationStatus = verification?.Status ?? TenantVerificationStatus.Draft, - EffectiveFrom = subscription?.EffectiveFrom ?? tenant.EffectiveFrom, - EffectiveTo = subscription?.EffectiveTo ?? tenant.EffectiveTo - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetTenantQuotaUsageHistoryQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetTenantQuotaUsageHistoryQueryHandler.cs deleted file mode 100644 index 4d46550..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetTenantQuotaUsageHistoryQueryHandler.cs +++ /dev/null @@ -1,186 +0,0 @@ -using MediatR; -using System.Data; -using System.Data.Common; -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Application.App.Tenants.Queries; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Data; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Results; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Tenants.Handlers; - -/// -/// 分页查询租户配额使用历史处理器。 -/// -public sealed class GetTenantQuotaUsageHistoryQueryHandler( - ITenantRepository tenantRepository, - ITenantProvider tenantProvider, - IDapperExecutor dapperExecutor) - : IRequestHandler> -{ - /// - public async Task> Handle(GetTenantQuotaUsageHistoryQuery request, CancellationToken cancellationToken) - { - // 1. 校验租户上下文(租户端禁止跨租户) - var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (currentTenantId <= 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识"); - } - - // 2. (空行后) 兼容旧调用:若传入 TenantId,则必须与当前租户一致 - if (request.TenantId > 0 && request.TenantId != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "无权查询其他租户配额历史"); - } - - // 3. (空行后) 校验租户存在 - _ = await tenantRepository.FindByIdAsync(currentTenantId, cancellationToken) - ?? throw new BusinessException(ErrorCodes.NotFound, "租户不存在"); - - // 4. (空行后) 规范化分页 - var page = request.Page <= 0 ? 1 : request.Page; - var pageSize = request.PageSize is <= 0 or > 100 ? 10 : request.PageSize; - var offset = (page - 1) * pageSize; - - // 5. (空行后) 查询总数 + 列表 - return await dapperExecutor.QueryAsync( - DatabaseConstants.AppDataSource, - DatabaseConnectionRole.Read, - async (connection, token) => - { - // 3.1 统计总数 - var total = await ExecuteScalarIntAsync( - connection, - BuildCountSql(), - [ - ("tenantId", currentTenantId), - ("quotaType", request.QuotaType.HasValue ? (int)request.QuotaType.Value : null), - ("startDate", request.StartDate), - ("endDate", request.EndDate) - ], - token); - - // 3.2 查询列表 - await using var listCommand = CreateCommand( - connection, - BuildListSql(), - [ - ("tenantId", currentTenantId), - ("quotaType", request.QuotaType.HasValue ? (int)request.QuotaType.Value : null), - ("startDate", request.StartDate), - ("endDate", request.EndDate), - ("offset", offset), - ("limit", pageSize) - ]); - - await using var reader = await listCommand.ExecuteReaderAsync(token); - var items = new List(); - while (await reader.ReadAsync(token)) - { - var quotaType = (TenantQuotaType)reader.GetInt32(0); - var usedValue = reader.GetDecimal(1); - var limitValue = reader.GetDecimal(2); - var recordedAt = reader.GetDateTime(3); - var changeType = (TenantQuotaUsageHistoryChangeType)reader.GetInt32(4); - decimal? changeAmount = reader.IsDBNull(5) ? null : reader.GetDecimal(5); - var changeReason = reader.IsDBNull(6) ? null : reader.GetString(6); - - // 3.2.1 映射 DTO - items.Add(new QuotaUsageHistoryDto - { - QuotaType = quotaType, - UsedValue = usedValue, - LimitValue = limitValue, - RecordedAt = recordedAt, - ChangeType = MapChangeType(changeType), - ChangeAmount = changeAmount, - ChangeReason = changeReason - }); - } - - // 3.3 返回分页 - return new PagedResult(items, page, pageSize, total); - }, - cancellationToken); - } - - private static string BuildCountSql() - { - return """ - select count(*) - from public.tenant_quota_usage_histories h - where h."DeletedAt" is null - and h."TenantId" = @tenantId - and (@quotaType::int is null or h."QuotaType" = @quotaType) - and (@startDate::timestamp with time zone is null or h."RecordedAt" >= @startDate) - and (@endDate::timestamp with time zone is null or h."RecordedAt" <= @endDate); - """; - } - - private static string BuildListSql() - { - return """ - select - h."QuotaType", - h."UsedValue", - h."LimitValue", - h."RecordedAt", - h."ChangeType", - h."ChangeAmount", - h."ChangeReason" - from public.tenant_quota_usage_histories h - where h."DeletedAt" is null - and h."TenantId" = @tenantId - and (@quotaType::int is null or h."QuotaType" = @quotaType) - and (@startDate::timestamp with time zone is null or h."RecordedAt" >= @startDate) - and (@endDate::timestamp with time zone is null or h."RecordedAt" <= @endDate) - order by h."RecordedAt" desc, h."Id" desc - offset @offset - limit @limit; - """; - } - - private static string MapChangeType(TenantQuotaUsageHistoryChangeType changeType) - { - return changeType switch - { - TenantQuotaUsageHistoryChangeType.Init => "init", - TenantQuotaUsageHistoryChangeType.Snapshot => "snapshot", - TenantQuotaUsageHistoryChangeType.Increase => "increase", - TenantQuotaUsageHistoryChangeType.Decrease => "decrease", - _ => "snapshot" - }; - } - - private static async Task ExecuteScalarIntAsync( - IDbConnection connection, - string sql, - (string Name, object? Value)[] parameters, - CancellationToken cancellationToken) - { - await using var command = CreateCommand(connection, sql, parameters); - var result = await command.ExecuteScalarAsync(cancellationToken); - return result is null or DBNull ? 0 : Convert.ToInt32(result); - } - - private static DbCommand CreateCommand(IDbConnection connection, string sql, (string Name, object? Value)[] parameters) - { - var command = connection.CreateCommand(); - command.CommandText = sql; - - foreach (var (name, value) in parameters) - { - var p = command.CreateParameter(); - p.ParameterName = name; - p.Value = value ?? DBNull.Value; - command.Parameters.Add(p); - } - - return (DbCommand)command; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetTenantsAnnouncementsQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetTenantsAnnouncementsQueryHandler.cs deleted file mode 100644 index 22b85d6..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetTenantsAnnouncementsQueryHandler.cs +++ /dev/null @@ -1,129 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Application.App.Tenants.Queries; -using TakeoutSaaS.Application.App.Tenants.Targeting; -using TakeoutSaaS.Application.Identity.Abstractions; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Results; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Tenants.Handlers; - -/// -/// 公告分页查询处理器。 -/// -public sealed class GetTenantsAnnouncementsQueryHandler( - ITenantAnnouncementRepository announcementRepository, - ITenantAnnouncementReadRepository announcementReadRepository, - ITenantProvider tenantProvider, - ICurrentUserAccessor? currentUserAccessor = null, - IAdminAuthService? adminAuthService = null, - IMiniAuthService? miniAuthService = null) - : IRequestHandler> -{ - /// - /// 分页查询公告列表。 - /// - /// 查询条件。 - /// 取消标记。 - /// 分页结果。 - public async Task> Handle(GetTenantsAnnouncementsQuery request, CancellationToken cancellationToken) - { - var tenantId = tenantProvider.GetCurrentTenantId(); - var effectiveAt = request.OnlyEffective == true ? DateTime.UtcNow : (DateTime?)null; - - // 计算分页参数 - var page = request.Page <= 0 ? 1 : request.Page; - var size = request.PageSize <= 0 ? 20 : request.PageSize; - - // 估算需要查询的数量:考虑到目标受众过滤可能会移除一些记录, - // 我们查询 3 倍的数量以确保有足够的结果 - var estimatedLimit = page * size * 3; - - // 1. 优化的数据库查询:应用排序和限制 - var announcements = await announcementRepository.SearchAsync( - tenantId, - request.Keyword, - request.Status, - request.AnnouncementType, - request.IsActive, - request.EffectiveFrom, - request.EffectiveTo, - effectiveAt, - orderByPriority: true, // 在数据库端排序 - limit: estimatedLimit, // 限制结果数量 - cancellationToken); - - // 2. 内存过滤:ScheduledPublishAt - if (effectiveAt.HasValue) - { - var at = effectiveAt.Value; - announcements = announcements - .Where(x => x.ScheduledPublishAt == null || x.ScheduledPublishAt <= at) - .ToList(); - } - - // 3. 目标受众过滤(在内存中,但数据量已大幅减少) - var targetContext = await AnnouncementTargetContextFactory.BuildAsync( - tenantProvider, - currentUserAccessor, - adminAuthService, - miniAuthService, - cancellationToken); - - var filtered = announcements - .Where(a => TargetTypeFilter.IsMatch(a, targetContext)) - .ToList(); - - // 注意:由于目标受众过滤可能移除记录,filtered.Count 可能小于请求的 size - // 这是可接受的,因为精确计算总数代价高昂 - - // 4. 分页(数据已在数据库层排序,这里只需 Skip/Take) - var pageItems = filtered - .Skip((page - 1) * size) - .Take(size) - .ToList(); - - // 5. 构建已读映射 - var announcementIds = pageItems.Select(x => x.Id).ToArray(); - var userId = targetContext.UserId; - - var readMap = new Dictionary(); - if (announcementIds.Length > 0) - { - var reads = new List(); - if (userId != 0) - { - var userReads = await announcementReadRepository.GetByAnnouncementAsync(tenantId, announcementIds, userId, cancellationToken); - reads.AddRange(userReads); - } - - var tenantReads = await announcementReadRepository.GetByAnnouncementAsync(tenantId, announcementIds, null, cancellationToken); - reads.AddRange(tenantReads); - - foreach (var read in reads.OrderByDescending(x => x.ReadAt)) - { - if (readMap.ContainsKey(read.AnnouncementId) && read.UserId.HasValue) - { - continue; - } - - readMap[read.AnnouncementId] = (true, read.ReadAt); - } - } - - // 6. 映射 DTO 并带上已读状态 - var items = pageItems - .Select(a => - { - readMap.TryGetValue(a.Id, out var read); - return a.ToDto(read.isRead, read.readAt); - }) - .ToList(); - - // 注意:由于我们使用了估算的 limit,总数是 filtered.Count 而不是数据库中的实际总数 - // 这是一个权衡:精确的总数需要额外的 COUNT 查询,代价较高 - return new PagedResult(items, page, size, filtered.Count); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetUnreadAnnouncementsQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetUnreadAnnouncementsQueryHandler.cs deleted file mode 100644 index fc5a445..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/GetUnreadAnnouncementsQueryHandler.cs +++ /dev/null @@ -1,76 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Application.App.Tenants.Queries; -using TakeoutSaaS.Application.App.Tenants.Targeting; -using TakeoutSaaS.Application.Identity.Abstractions; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Results; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Tenants.Handlers; - -/// -/// 未读公告查询处理器。 -/// -public sealed class GetUnreadAnnouncementsQueryHandler( - ITenantAnnouncementRepository announcementRepository, - ITenantProvider tenantProvider, - ICurrentUserAccessor? currentUserAccessor = null, - IAdminAuthService? adminAuthService = null, - IMiniAuthService? miniAuthService = null) - : IRequestHandler> -{ - /// - public async Task> Handle(GetUnreadAnnouncementsQuery request, CancellationToken cancellationToken) - { - var tenantId = tenantProvider.GetCurrentTenantId(); - var userId = currentUserAccessor?.UserId ?? 0; - var now = DateTime.UtcNow; - - // 1. 查询未读公告(已发布/启用/有效期内) - var announcements = await announcementRepository.SearchUnreadAsync( - tenantId, - userId == 0 ? null : userId, - AnnouncementStatus.Published, - true, - now, - cancellationToken); - - announcements = announcements - .Where(x => x.ScheduledPublishAt == null || x.ScheduledPublishAt <= now) - .ToList(); - - // 2. 目标受众过滤 - var targetContext = await AnnouncementTargetContextFactory.BuildAsync( - tenantProvider, - currentUserAccessor, - adminAuthService, - miniAuthService, - cancellationToken); - - var filtered = announcements - .Where(a => TargetTypeFilter.IsMatch(a, targetContext)) - .ToList(); - - // 3. 排序与分页 - var ordered = filtered - .OrderByDescending(x => x.Priority) - .ThenByDescending(x => x.EffectiveFrom) - .ToList(); - - var page = request.Page <= 0 ? 1 : request.Page; - var size = request.PageSize <= 0 ? 20 : request.PageSize; - var pageItems = ordered - .Skip((page - 1) * size) - .Take(size) - .ToList(); - - var items = pageItems - .Select(x => x.ToDto(false, null)) - .ToList(); - - return new PagedResult(items, page, size, ordered.Count); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/MarkAnnouncementAsReadCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/MarkAnnouncementAsReadCommandHandler.cs deleted file mode 100644 index caa495c..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/MarkAnnouncementAsReadCommandHandler.cs +++ /dev/null @@ -1,100 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Commands; -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Application.App.Tenants.Targeting; -using TakeoutSaaS.Application.Identity.Abstractions; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Tenants.Handlers; - -/// -/// 标记公告已读处理器。 -/// -public sealed class MarkAnnouncementAsReadCommandHandler( - ITenantAnnouncementRepository announcementRepository, - ITenantAnnouncementReadRepository readRepository, - ITenantProvider tenantProvider, - ICurrentUserAccessor? currentUserAccessor = null, - IAdminAuthService? adminAuthService = null, - IMiniAuthService? miniAuthService = null) - : IRequestHandler -{ - /// - /// 标记公告已读。 - /// - /// 标记命令。 - /// 取消标记。 - /// 公告 DTO 或 null。 - public async Task Handle(MarkAnnouncementAsReadCommand request, CancellationToken cancellationToken) - { - var tenantId = tenantProvider.GetCurrentTenantId(); - - // 1. 查询公告 - var announcement = await announcementRepository.FindByIdAsync(tenantId, request.AnnouncementId, cancellationToken); - if (announcement == null) - { - return null; - } - - // 2. 仅允许已发布且在有效期内的公告标记已读 - var now = DateTime.UtcNow; - if (announcement.Status != AnnouncementStatus.Published) - { - return null; - } - - if (announcement.EffectiveFrom > now || (announcement.EffectiveTo.HasValue && announcement.EffectiveTo.Value < now)) - { - return null; - } - - if (announcement.ScheduledPublishAt.HasValue && announcement.ScheduledPublishAt.Value > now) - { - return null; - } - - // 3. 目标受众过滤 - var targetContext = await AnnouncementTargetContextFactory.BuildAsync( - tenantProvider, - currentUserAccessor, - adminAuthService, - miniAuthService, - cancellationToken); - - if (!TargetTypeFilter.IsMatch(announcement, targetContext)) - { - return null; - } - - // 4. 确定用户标识 - var userId = targetContext.UserId == 0 ? (long?)null : targetContext.UserId; - var existing = await readRepository.FindAsync(tenantId, announcement.Id, userId, cancellationToken); - - if (existing == null && userId.HasValue) - { - existing = await readRepository.FindAsync(tenantId, announcement.Id, null, cancellationToken); - } - - // 5. 如未读则写入已读记录 - if (existing == null) - { - var record = new TenantAnnouncementRead - { - TenantId = tenantId, - AnnouncementId = announcement.Id, - UserId = userId, - ReadAt = now - }; - - await readRepository.AddAsync(record, cancellationToken); - await readRepository.SaveChangesAsync(cancellationToken); - existing = record; - } - - return announcement.ToDto(true, existing.ReadAt); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/MarkTenantNotificationReadCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/MarkTenantNotificationReadCommandHandler.cs deleted file mode 100644 index 7d75258..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/MarkTenantNotificationReadCommandHandler.cs +++ /dev/null @@ -1,58 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Commands; -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Tenants.Handlers; - -/// -/// 标记通知已读处理器。 -/// -public sealed class MarkTenantNotificationReadCommandHandler( - ITenantNotificationRepository notificationRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - /// 标记通知已读。 - /// - /// 标记命令。 - /// 取消标记。 - /// 通知 DTO 或 null。 - public async Task Handle(MarkTenantNotificationReadCommand request, CancellationToken cancellationToken) - { - // 1. 校验租户上下文(租户端禁止跨租户) - var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (currentTenantId <= 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识"); - } - - // 2. (空行后) 兼容旧调用:若传入 TenantId,则必须与当前租户一致 - if (request.TenantId > 0 && request.TenantId != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "无权标记其他租户通知"); - } - - // 3. (空行后) 查询通知 - var notification = await notificationRepository.FindByIdAsync(currentTenantId, request.NotificationId, cancellationToken); - if (notification == null) - { - return null; - } - - // 4. (空行后) 若未读则标记已读 - if (notification.ReadAt == null) - { - notification.ReadAt = DateTime.UtcNow; - await notificationRepository.UpdateAsync(notification, cancellationToken); - await notificationRepository.SaveChangesAsync(cancellationToken); - } - - // 5. (空行后) 返回 DTO - return notification.ToDto(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/PublishAnnouncementCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/PublishAnnouncementCommandHandler.cs deleted file mode 100644 index 1162527..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/PublishAnnouncementCommandHandler.cs +++ /dev/null @@ -1,84 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Commands; -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Application.Messaging.Abstractions; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Events; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Tenants.Handlers; - -/// -/// 发布公告处理器。 -/// -public sealed class PublishAnnouncementCommandHandler( - ITenantAnnouncementRepository announcementRepository, - ITenantProvider tenantProvider, - IEventPublisher eventPublisher) - : IRequestHandler -{ - /// - public async Task Handle(PublishAnnouncementCommand request, CancellationToken cancellationToken) - { - if (request.RowVersion == null || request.RowVersion.Length == 0) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "RowVersion 不能为空"); - } - - // 1. 查询公告 - var tenantId = tenantProvider.GetCurrentTenantId(); - var announcement = await announcementRepository.FindByIdAsync(tenantId, request.AnnouncementId, cancellationToken); - if (announcement == null) - { - return null; - } - - // 2. 校验状态与目标受众 - if (string.IsNullOrWhiteSpace(announcement.TargetType)) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "目标受众类型不能为空"); - } - - if (announcement.Status == AnnouncementStatus.Published) - { - throw new BusinessException(ErrorCodes.Conflict, "公告已发布"); - } - - if (announcement.Status != AnnouncementStatus.Draft && announcement.Status != AnnouncementStatus.Revoked) - { - throw new BusinessException(ErrorCodes.Conflict, "仅草稿或已撤销公告允许发布"); - } - - // 3. 发布公告 - announcement.Status = AnnouncementStatus.Published; - announcement.PublishedAt = DateTime.UtcNow; - announcement.RevokedAt = null; - announcement.RowVersion = request.RowVersion; - - try - { - await announcementRepository.UpdateAsync(announcement, cancellationToken); - await announcementRepository.SaveChangesAsync(cancellationToken); - } - catch (Exception exception) when (exception.GetType().Name == "DbUpdateConcurrencyException") - { - throw new BusinessException(ErrorCodes.Conflict, "公告已被修改,请刷新后重试"); - } - - // 4. 发布领域事件 - await eventPublisher.PublishAsync( - "tenant-announcement.published", - new AnnouncementPublished - { - AnnouncementId = announcement.Id, - PublishedAt = announcement.PublishedAt ?? DateTime.UtcNow, - TargetType = announcement.TargetType - }, - cancellationToken); - - return announcement.ToDto(false, null); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/RevokeAnnouncementCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/RevokeAnnouncementCommandHandler.cs deleted file mode 100644 index 01a57d5..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/RevokeAnnouncementCommandHandler.cs +++ /dev/null @@ -1,77 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Commands; -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Application.Messaging.Abstractions; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Events; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Tenants.Handlers; - -/// -/// 撤销公告处理器。 -/// -public sealed class RevokeAnnouncementCommandHandler( - ITenantAnnouncementRepository announcementRepository, - ITenantProvider tenantProvider, - IEventPublisher eventPublisher) - : IRequestHandler -{ - /// - public async Task Handle(RevokeAnnouncementCommand request, CancellationToken cancellationToken) - { - if (request.RowVersion == null || request.RowVersion.Length == 0) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "RowVersion 不能为空"); - } - - // 1. 查询公告 - var tenantId = tenantProvider.GetCurrentTenantId(); - var announcement = await announcementRepository.FindByIdAsync(tenantId, request.AnnouncementId, cancellationToken); - if (announcement == null) - { - return null; - } - - // 2. 校验状态 - if (announcement.Status != AnnouncementStatus.Published) - { - if (announcement.Status == AnnouncementStatus.Revoked) - { - throw new BusinessException(ErrorCodes.Conflict, "公告已撤销"); - } - - throw new BusinessException(ErrorCodes.Conflict, "仅已发布公告允许撤销"); - } - - // 3. 撤销公告 - announcement.Status = AnnouncementStatus.Revoked; - announcement.RevokedAt = DateTime.UtcNow; - announcement.RowVersion = request.RowVersion; - - try - { - await announcementRepository.UpdateAsync(announcement, cancellationToken); - await announcementRepository.SaveChangesAsync(cancellationToken); - } - catch (Exception exception) when (exception.GetType().Name == "DbUpdateConcurrencyException") - { - throw new BusinessException(ErrorCodes.Conflict, "公告已被修改,请刷新后重试"); - } - - // 4. 发布领域事件 - await eventPublisher.PublishAsync( - "tenant-announcement.revoked", - new AnnouncementRevoked - { - AnnouncementId = announcement.Id, - RevokedAt = announcement.RevokedAt ?? DateTime.UtcNow - }, - cancellationToken); - - return announcement.ToDto(false, null); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/SearchTenantBillsQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/SearchTenantBillsQueryHandler.cs deleted file mode 100644 index 3286117..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/SearchTenantBillsQueryHandler.cs +++ /dev/null @@ -1,53 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Application.App.Tenants.Queries; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Results; -using TakeoutSaaS.Shared.Abstractions.Tenancy; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; - -namespace TakeoutSaaS.Application.App.Tenants.Handlers; - -/// -/// 账单分页查询处理器。 -/// -public sealed class SearchTenantBillsQueryHandler( - ITenantBillingRepository billingRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - /// - /// 分页查询账单列表。 - /// - /// 查询条件。 - /// 取消标记。 - /// 分页结果。 - public async Task> Handle(SearchTenantBillsQuery request, CancellationToken cancellationToken) - { - // 1. 校验租户上下文(租户端禁止跨租户) - var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (currentTenantId <= 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识"); - } - - // 2. (空行后) 兼容旧调用:若传入 TenantId,则必须与当前租户一致 - if (request.TenantId > 0 && request.TenantId != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "无权查询其他租户账单"); - } - - // 3. (空行后) 查询账单 - var bills = await billingRepository.SearchAsync(currentTenantId, request.Status, request.From, request.To, cancellationToken); - - // 4. (空行后) 排序与分页 - var ordered = bills.OrderByDescending(x => x.PeriodEnd).ToList(); - var page = request.Page <= 0 ? 1 : request.Page; - var size = request.PageSize <= 0 ? 20 : request.PageSize; - var items = ordered.Skip((page - 1) * size).Take(size).Select(x => x.ToDto()).ToList(); - - // 5. (空行后) 返回分页结果 - return new PagedResult(items, page, size, ordered.Count); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/SearchTenantNotificationsQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/SearchTenantNotificationsQueryHandler.cs deleted file mode 100644 index c37a1df..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/SearchTenantNotificationsQueryHandler.cs +++ /dev/null @@ -1,59 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Application.App.Tenants.Queries; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Results; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Tenants.Handlers; - -/// -/// 通知分页查询处理器。 -/// -public sealed class SearchTenantNotificationsQueryHandler( - ITenantNotificationRepository notificationRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - /// - /// 分页查询通知列表。 - /// - /// 查询条件。 - /// 取消标记。 - /// 分页结果。 - public async Task> Handle(SearchTenantNotificationsQuery request, CancellationToken cancellationToken) - { - // 1. 校验租户上下文(租户端禁止跨租户) - var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (currentTenantId <= 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识"); - } - - // 2. (空行后) 兼容旧调用:若传入 TenantId,则必须与当前租户一致 - if (request.TenantId > 0 && request.TenantId != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "无权查询其他租户通知"); - } - - // 3. (空行后) 查询通知 - var notifications = await notificationRepository.SearchAsync( - currentTenantId, - request.Severity, - request.UnreadOnly, - null, - null, - cancellationToken); - - // 4. (空行后) 排序与分页 - var ordered = notifications.OrderByDescending(x => x.SentAt).ToList(); - var page = request.Page <= 0 ? 1 : request.Page; - var size = request.PageSize <= 0 ? 20 : request.PageSize; - var items = ordered.Skip((page - 1) * size).Take(size).Select(x => x.ToDto()).ToList(); - - // 5. (空行后) 返回分页结果 - return new PagedResult(items, page, size, ordered.Count); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/SelfRegisterTenantCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/SelfRegisterTenantCommandHandler.cs deleted file mode 100644 index 4d15ddf..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/SelfRegisterTenantCommandHandler.cs +++ /dev/null @@ -1,140 +0,0 @@ -using MediatR; -using Microsoft.AspNetCore.Identity; -using TakeoutSaaS.Application.App.Tenants.Commands; -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Application.Identity.Commands; -using TakeoutSaaS.Domain.Identity.Entities; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Ids; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Tenants.Handlers; - -/// -/// 自助注册租户处理器。 -/// -public sealed class SelfRegisterTenantCommandHandler( - ITenantRepository tenantRepository, - IIdentityUserRepository identityUserRepository, - IRoleRepository roleRepository, - IPasswordHasher passwordHasher, - IIdGenerator idGenerator, - IMediator mediator, - ITenantContextAccessor tenantContextAccessor) - : IRequestHandler -{ - /// - public async Task Handle(SelfRegisterTenantCommand request, CancellationToken cancellationToken) - { - // 1. 唯一性校验 - var normalizedAccount = request.AdminAccount.Trim(); - if (await identityUserRepository.ExistsByAccountAsync(normalizedAccount, cancellationToken)) - { - throw new BusinessException(ErrorCodes.Conflict, $"账号 {normalizedAccount} 已存在"); - } - - // 1.2 校验手机号唯一性 - var normalizedPhone = request.AdminPhone.Trim(); - if (await tenantRepository.ExistsByContactPhoneAsync(normalizedPhone, cancellationToken)) - { - throw new BusinessException(ErrorCodes.Conflict, $"手机号 {normalizedPhone} 已注册"); - } - - // 2. 生成租户标识与编码 - var tenantId = idGenerator.NextId(); - var tenantCode = $"t{tenantId}"; - - // 3. 构建租户(无订阅,待审核) - var tenant = new Tenant - { - Id = tenantId, - Code = tenantCode, - Name = normalizedAccount, - ShortName = string.IsNullOrWhiteSpace(request.AdminDisplayName) ? normalizedAccount : request.AdminDisplayName!.Trim(), - ContactName = string.IsNullOrWhiteSpace(request.AdminDisplayName) ? normalizedAccount : request.AdminDisplayName!.Trim(), - ContactPhone = normalizedPhone, - ContactEmail = request.AdminEmail, - Status = TenantStatus.PendingReview, - EffectiveFrom = null, - EffectiveTo = null - }; - - // 4. 写入审计日志 - var auditLog = new TenantAuditLog - { - TenantId = tenant.Id, - Action = TenantAuditAction.RegistrationSubmitted, - Title = "自助注册", - Description = "自助注册提交,等待补充资料与审核" - }; - - // 5. 持久化租户与审计 - await tenantRepository.AddTenantAsync(tenant, cancellationToken); - await tenantRepository.AddAuditLogAsync(auditLog, cancellationToken); - await tenantRepository.SaveChangesAsync(cancellationToken); - - // 6. 临时切换租户上下文,保证身份与权限写入正确 - var previousContext = tenantContextAccessor.Current; - tenantContextAccessor.Current = new TenantContext(tenant.Id, tenant.Code, "self-register"); - try - { - // 7. 使用用户自设密码创建管理员 - var adminUser = new IdentityUser - { - TenantId = tenant.Id, - Account = normalizedAccount, - DisplayName = string.IsNullOrWhiteSpace(request.AdminDisplayName) ? normalizedAccount : request.AdminDisplayName!.Trim(), - PasswordHash = string.Empty, - Phone = normalizedPhone, - Email = string.IsNullOrWhiteSpace(request.AdminEmail) ? null : request.AdminEmail.Trim() - }; - adminUser.PasswordHash = passwordHasher.HashPassword(adminUser, request.AdminPassword); - await identityUserRepository.AddAsync(adminUser, cancellationToken); - await identityUserRepository.SaveChangesAsync(cancellationToken); - - // 7.1 回填主管理员标识,确保后续伪装登录/重置管理员等能力可用 - tenant.PrimaryOwnerUserId = adminUser.Id; - await tenantRepository.UpdateTenantAsync(tenant, cancellationToken); - await tenantRepository.SaveChangesAsync(cancellationToken); - - // 8. 初始化租户管理员角色模板 - await mediator.Send(new InitializeRoleTemplatesCommand - { - TemplateCodes = new[] { "tenant-admin" } - }, cancellationToken); - - // 9. 绑定租户管理员角色 - var tenantAdminRole = await roleRepository.FindByCodeAsync("tenant-admin", tenant.Id, cancellationToken); - if (tenantAdminRole != null) - { - await mediator.Send(new AssignUserRolesCommand - { - UserId = adminUser.Id, - RoleIds = new[] { tenantAdminRole.Id } - }, cancellationToken); - } - - // 10. 返回注册结果 - return new SelfRegisterResultDto - { - TenantId = tenant.Id, - Code = tenant.Code, - Status = tenant.Status, - VerificationStatus = TenantVerificationStatus.Draft, - EffectiveFrom = tenant.EffectiveFrom, - EffectiveTo = tenant.EffectiveTo, - AdminAccount = adminUser.Account - }; - } - finally - { - // 11. 恢复上下文 - tenantContextAccessor.Current = previousContext; - } - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/SubmitTenantVerificationCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/SubmitTenantVerificationCommandHandler.cs deleted file mode 100644 index 93802db..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/SubmitTenantVerificationCommandHandler.cs +++ /dev/null @@ -1,80 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Commands; -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Ids; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Tenants.Handlers; - -/// -/// 实名资料提交流程。 -/// -public sealed class SubmitTenantVerificationCommandHandler( - ITenantRepository tenantRepository, - ITenantProvider tenantProvider, - IIdGenerator idGenerator) - : IRequestHandler -{ - /// - public async Task Handle(SubmitTenantVerificationCommand request, CancellationToken cancellationToken) - { - // 1. 校验租户上下文(租户端禁止跨租户) - var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (currentTenantId <= 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识"); - } - - // 2. (空行后) 兼容旧调用:若传入 TenantId,则必须与当前租户一致 - if (request.TenantId > 0 && request.TenantId != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "无权提交其他租户实名认证资料"); - } - - // 3. (空行后) 获取租户 - var tenant = await tenantRepository.FindByIdAsync(currentTenantId, cancellationToken) - ?? throw new BusinessException(ErrorCodes.NotFound, "租户不存在"); - - // 4. (空行后) 读取或初始化实名资料 - var profile = await tenantRepository.GetVerificationProfileAsync(currentTenantId, cancellationToken) - ?? new TenantVerificationProfile { Id = idGenerator.NextId(), TenantId = tenant.Id }; - - // 5. (空行后) 填充资料 - profile.BusinessLicenseNumber = request.BusinessLicenseNumber; - profile.BusinessLicenseUrl = request.BusinessLicenseUrl; - profile.LegalPersonName = request.LegalPersonName; - profile.LegalPersonIdNumber = request.LegalPersonIdNumber; - profile.LegalPersonIdFrontUrl = request.LegalPersonIdFrontUrl; - profile.LegalPersonIdBackUrl = request.LegalPersonIdBackUrl; - profile.BankAccountName = request.BankAccountName; - profile.BankAccountNumber = request.BankAccountNumber; - profile.BankName = request.BankName; - profile.AdditionalDataJson = request.AdditionalDataJson; - profile.Status = TenantVerificationStatus.Pending; - profile.SubmittedAt = DateTime.UtcNow; - profile.ReviewedAt = null; - profile.ReviewRemarks = null; - profile.ReviewedBy = null; - profile.ReviewedByName = null; - - // 6. (空行后) 保存资料并记录审计 - await tenantRepository.UpsertVerificationProfileAsync(profile, cancellationToken); - await tenantRepository.AddAuditLogAsync(new TenantAuditLog - { - TenantId = tenant.Id, - Action = TenantAuditAction.VerificationSubmitted, - Title = "提交实名认证资料", - Description = request.BusinessLicenseNumber - }, cancellationToken); - await tenantRepository.SaveChangesAsync(cancellationToken); - - // 7. (空行后) 返回 DTO - return profile.ToVerificationDto() - ?? throw new BusinessException(ErrorCodes.InternalServerError, "实名资料保存失败"); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/UpdateTenantAnnouncementCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/UpdateTenantAnnouncementCommandHandler.cs deleted file mode 100644 index 4df53f2..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/UpdateTenantAnnouncementCommandHandler.cs +++ /dev/null @@ -1,90 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Commands; -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Application.App.Tenants.Targeting; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Tenants.Handlers; - -/// -/// 更新公告处理器。 -/// -public sealed class UpdateTenantAnnouncementCommandHandler( - ITenantAnnouncementRepository announcementRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - public async Task Handle(UpdateTenantAnnouncementCommand request, CancellationToken cancellationToken) - { - // 1. 校验租户上下文(租户端禁止跨租户) - var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (currentTenantId <= 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识"); - } - - // 2. (空行后) 兼容旧调用:若传入 TenantId,则必须与当前租户一致 - if (request.TenantId > 0 && request.TenantId != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "无权编辑其他租户公告"); - } - - // 3. (空行后) 校验输入 - if (string.IsNullOrWhiteSpace(request.Title) || string.IsNullOrWhiteSpace(request.Content)) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "公告标题和内容不能为空"); - } - - if (request.RowVersion == null || request.RowVersion.Length == 0) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "RowVersion 不能为空"); - } - // 3.1 (空行后) 校验目标受众类型:租户端禁止跨租户目标类型 - if (!TenantAnnouncementTargetTypePolicy.IsAllowed(request.TargetType)) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "租户端不支持该目标受众类型"); - } - - // 4. (空行后) 查询公告 - var announcement = await announcementRepository.FindByIdAsync(currentTenantId, request.AnnouncementId, cancellationToken); - if (announcement == null) - { - return null; - } - - if (announcement.Status != AnnouncementStatus.Draft) - { - if (announcement.Status == AnnouncementStatus.Published) - { - throw new BusinessException(ErrorCodes.Conflict, "已发布公告不可编辑,要编辑已发布公告,请先撤销"); - } - - throw new BusinessException(ErrorCodes.Conflict, "仅草稿公告允许编辑"); - } - - // 5. (空行后) 更新字段 - announcement.Title = request.Title.Trim(); - announcement.Content = request.Content; - announcement.TargetType = TenantAnnouncementTargetTypePolicy.Normalize(request.TargetType); - announcement.TargetParameters = request.TargetParameters; - announcement.RowVersion = request.RowVersion; - - // 6. (空行后) 持久化 - try - { - await announcementRepository.UpdateAsync(announcement, cancellationToken); - await announcementRepository.SaveChangesAsync(cancellationToken); - } - catch (Exception exception) when (exception.GetType().Name == "DbUpdateConcurrencyException") - { - throw new BusinessException(ErrorCodes.Conflict, "公告已被修改,请刷新后重试"); - } - - // 7. (空行后) 返回 DTO - return announcement.ToDto(false, null); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/UpdateTenantCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/UpdateTenantCommandHandler.cs deleted file mode 100644 index b4ac9ff..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/UpdateTenantCommandHandler.cs +++ /dev/null @@ -1,81 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Tenants.Commands; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Tenants.Handlers; - -/// -/// 更新租户基础信息处理器。 -/// -public sealed class UpdateTenantCommandHandler( - ITenantRepository tenantRepository, - ITenantProvider tenantProvider, - ILogger logger) - : IRequestHandler -{ - /// - public async Task Handle(UpdateTenantCommand request, CancellationToken cancellationToken) - { - // 1. 校验租户上下文(租户端禁止跨租户) - var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (currentTenantId <= 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识"); - } - - // 2. (空行后) 兼容旧调用:若传入 TenantId,则必须与当前租户一致 - if (request.TenantId > 0 && request.TenantId != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "无权操作其他租户信息"); - } - - // 3. (空行后) 参数校验:租户名称 - if (string.IsNullOrWhiteSpace(request.Name)) - { - throw new BusinessException(ErrorCodes.BadRequest, "租户名称不能为空"); - } - - // 4. (空行后) 查询租户 - var tenant = await tenantRepository.FindByIdAsync(currentTenantId, cancellationToken) - ?? throw new BusinessException(ErrorCodes.NotFound, "租户不存在"); - - // 5. (空行后) 校验租户名称唯一性(排除自身) - var normalizedName = request.Name.Trim(); - if (await tenantRepository.ExistsByNameAsync(normalizedName, excludeTenantId: currentTenantId, cancellationToken)) - { - throw new BusinessException(ErrorCodes.Conflict, $"租户名称 {normalizedName} 已存在"); - } - - // 6. (空行后) 校验联系人手机号唯一性(仅当填写时) - if (!string.IsNullOrWhiteSpace(request.ContactPhone)) - { - var normalizedPhone = request.ContactPhone.Trim(); - var existingTenantId = await tenantRepository.FindTenantIdByContactPhoneAsync(normalizedPhone, cancellationToken); - if (existingTenantId.HasValue && existingTenantId.Value != currentTenantId) - { - throw new BusinessException(ErrorCodes.Conflict, $"手机号 {normalizedPhone} 已注册"); - } - } - - // 7. (空行后) 更新基础信息(禁止修改 Code) - tenant.Name = normalizedName; - tenant.ShortName = string.IsNullOrWhiteSpace(request.ShortName) ? null : request.ShortName.Trim(); - tenant.Industry = string.IsNullOrWhiteSpace(request.Industry) ? null : request.Industry.Trim(); - tenant.ContactName = string.IsNullOrWhiteSpace(request.ContactName) ? null : request.ContactName.Trim(); - tenant.ContactPhone = string.IsNullOrWhiteSpace(request.ContactPhone) ? null : request.ContactPhone.Trim(); - tenant.ContactEmail = string.IsNullOrWhiteSpace(request.ContactEmail) ? null : request.ContactEmail.Trim(); - - // 8. (空行后) 持久化更新 - await tenantRepository.UpdateTenantAsync(tenant, cancellationToken); - await tenantRepository.SaveChangesAsync(cancellationToken); - - // 9. (空行后) 记录日志 - logger.LogInformation("已更新租户基础信息 {TenantId}", tenant.Id); - - return Unit.Value; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetAnnouncementByIdQuery.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetAnnouncementByIdQuery.cs deleted file mode 100644 index e889dff..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetAnnouncementByIdQuery.cs +++ /dev/null @@ -1,20 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Dto; - -namespace TakeoutSaaS.Application.App.Tenants.Queries; - -/// -/// 公告详情查询。 -/// -public sealed record GetAnnouncementByIdQuery : IRequest -{ - /// - /// 租户 ID(雪花算法,兼容旧调用,实际以当前租户为准)。 - /// - public long TenantId { get; init; } - - /// - /// 公告 ID。 - /// - public long AnnouncementId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetPublicTenantPackagesQuery.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetPublicTenantPackagesQuery.cs deleted file mode 100644 index 3c56e95..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetPublicTenantPackagesQuery.cs +++ /dev/null @@ -1,21 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.App.Tenants.Queries; - -/// -/// 公共场景分页查询启用套餐。 -/// -public sealed record GetPublicTenantPackagesQuery : IRequest> -{ - /// - /// 页码。 - /// - public int Page { get; init; } = 1; - - /// - /// 每页条数。 - /// - public int PageSize { get; init; } = 20; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetTenantBillQuery.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetTenantBillQuery.cs deleted file mode 100644 index a5ece15..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetTenantBillQuery.cs +++ /dev/null @@ -1,20 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Dto; - -namespace TakeoutSaaS.Application.App.Tenants.Queries; - -/// -/// 获取账单详情查询。 -/// -public sealed record GetTenantBillQuery : IRequest -{ - /// - /// 租户 ID(雪花算法)。 - /// - public long TenantId { get; init; } - - /// - /// 账单 ID。 - /// - public long BillingId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetTenantPackageByIdQuery.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetTenantPackageByIdQuery.cs deleted file mode 100644 index 252b5fe..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetTenantPackageByIdQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Dto; - -namespace TakeoutSaaS.Application.App.Tenants.Queries; - -/// -/// 获取套餐详情查询。 -/// -public sealed record GetTenantPackageByIdQuery : IRequest -{ - /// - /// 套餐 ID。 - /// - public long TenantPackageId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetTenantProgressQuery.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetTenantProgressQuery.cs deleted file mode 100644 index 214e600..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetTenantProgressQuery.cs +++ /dev/null @@ -1,17 +0,0 @@ -using MediatR; -using System.ComponentModel.DataAnnotations; -using TakeoutSaaS.Application.App.Tenants.Dto; - -namespace TakeoutSaaS.Application.App.Tenants.Queries; - -/// -/// 租户入住进度查询。 -/// -public sealed record GetTenantProgressQuery : IRequest -{ - /// - /// 租户 ID(雪花算法)。 - /// - [Required] - public long TenantId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetTenantQuotaUsageHistoryQuery.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetTenantQuotaUsageHistoryQuery.cs deleted file mode 100644 index e49907d..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetTenantQuotaUsageHistoryQuery.cs +++ /dev/null @@ -1,43 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.App.Tenants.Queries; - -/// -/// 分页查询租户配额使用历史。 -/// -public sealed record GetTenantQuotaUsageHistoryQuery : IRequest> -{ - /// - /// 租户 ID。 - /// - public long TenantId { get; init; } - - /// - /// 页码(从 1 开始)。 - /// - public int Page { get; init; } = 1; - - /// - /// 每页大小。 - /// - public int PageSize { get; init; } = 10; - - /// - /// 开始时间(UTC/带时区均可),为空不限制。 - /// - public DateTime? StartDate { get; init; } - - /// - /// 结束时间(UTC/带时区均可),为空不限制。 - /// - public DateTime? EndDate { get; init; } - - /// - /// 配额类型过滤,为空不过滤。 - /// - public TenantQuotaType? QuotaType { get; init; } -} - diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetTenantsAnnouncementsQuery.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetTenantsAnnouncementsQuery.cs deleted file mode 100644 index 87f5be5..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetTenantsAnnouncementsQuery.cs +++ /dev/null @@ -1,62 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.App.Tenants.Queries; - -/// -/// 分页查询租户公告。 -/// -public sealed record GetTenantsAnnouncementsQuery : IRequest> -{ - /// - /// 租户 ID(雪花算法)。 - /// - public long TenantId { get; init; } - - /// - /// 公告类型筛选。 - /// - public TenantAnnouncementType? AnnouncementType { get; init; } - - /// - /// 公告状态筛选。 - /// - public AnnouncementStatus? Status { get; init; } - - /// - /// 关键词搜索(标题/内容)。 - /// - public string? Keyword { get; init; } - - /// - /// 是否筛选启用状态。 - /// - public bool? IsActive { get; init; } - - /// - /// 生效开始时间筛选(UTC)。 - /// - public DateTime? EffectiveFrom { get; init; } - - /// - /// 生效结束时间筛选(UTC)。 - /// - public DateTime? EffectiveTo { get; init; } - - /// - /// 仅返回当前有效期内的公告。 - /// - public bool? OnlyEffective { get; init; } - - /// - /// 页码(从 1 开始)。 - /// - public int Page { get; init; } = 1; - - /// - /// 每页条数。 - /// - public int PageSize { get; init; } = 20; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetUnreadAnnouncementsQuery.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetUnreadAnnouncementsQuery.cs deleted file mode 100644 index d0972a7..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetUnreadAnnouncementsQuery.cs +++ /dev/null @@ -1,21 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.App.Tenants.Queries; - -/// -/// 查询未读公告。 -/// -public sealed record GetUnreadAnnouncementsQuery : IRequest> -{ - /// - /// 页码(从 1 开始)。 - /// - public int Page { get; init; } = 1; - - /// - /// 每页条数。 - /// - public int PageSize { get; init; } = 20; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/SearchTenantBillsQuery.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/SearchTenantBillsQuery.cs deleted file mode 100644 index 67d0103..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/SearchTenantBillsQuery.cs +++ /dev/null @@ -1,42 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.App.Tenants.Queries; - -/// -/// 分页查询租户账单。 -/// -public sealed record SearchTenantBillsQuery : IRequest> -{ - /// - /// 租户 ID(雪花算法)。 - /// - public long TenantId { get; init; } - - /// - /// 账单状态筛选。 - /// - public TenantBillingStatus? Status { get; init; } - - /// - /// 账单起始时间(UTC)筛选。 - /// - public DateTime? From { get; init; } - - /// - /// 账单结束时间(UTC)筛选。 - /// - public DateTime? To { get; init; } - - /// - /// 页码(从 1 开始)。 - /// - public int Page { get; init; } = 1; - - /// - /// 每页条数。 - /// - public int PageSize { get; init; } = 20; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/SearchTenantNotificationsQuery.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/SearchTenantNotificationsQuery.cs deleted file mode 100644 index ff5e8eb..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/SearchTenantNotificationsQuery.cs +++ /dev/null @@ -1,37 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.App.Tenants.Queries; - -/// -/// 分页查询租户通知。 -/// -public sealed record SearchTenantNotificationsQuery : IRequest> -{ - /// - /// 租户 ID(雪花算法)。 - /// - public long TenantId { get; init; } - - /// - /// 通知等级筛选。 - /// - public TenantNotificationSeverity? Severity { get; init; } - - /// - /// 仅返回未读通知。 - /// - public bool? UnreadOnly { get; init; } - - /// - /// 页码(从 1 开始)。 - /// - public int Page { get; init; } = 1; - - /// - /// 每页条数。 - /// - public int PageSize { get; init; } = 20; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Targeting/AnnouncementTargetContextFactory.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Targeting/AnnouncementTargetContextFactory.cs deleted file mode 100644 index a8e61fd..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Targeting/AnnouncementTargetContextFactory.cs +++ /dev/null @@ -1,58 +0,0 @@ -using TakeoutSaaS.Application.Identity.Abstractions; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.App.Tenants.Targeting; - -/// -/// 目标受众上下文构建器。 -/// -internal static class AnnouncementTargetContextFactory -{ - /// - /// 构建当前用户的目标上下文。 - /// - public static async Task BuildAsync( - ITenantProvider tenantProvider, - ICurrentUserAccessor? currentUserAccessor, - IAdminAuthService? adminAuthService, - IMiniAuthService? miniAuthService, - CancellationToken cancellationToken) - { - var tenantId = tenantProvider.GetCurrentTenantId(); - var userId = currentUserAccessor?.UserId ?? 0; - long? merchantId = null; - IReadOnlyCollection roles = Array.Empty(); - IReadOnlyCollection permissions = Array.Empty(); - - if (userId != 0) - { - CurrentUserProfile? profile = null; - if (adminAuthService != null) - { - profile = await adminAuthService.GetProfileAsync(userId, cancellationToken); - } - else if (miniAuthService != null) - { - profile = await miniAuthService.GetProfileAsync(userId, cancellationToken); - } - - if (profile != null) - { - merchantId = profile.MerchantId; - roles = profile.Roles ?? Array.Empty(); - permissions = profile.Permissions ?? Array.Empty(); - } - } - - return new AnnouncementTargetContext - { - TenantId = tenantId, - UserId = userId, - MerchantId = merchantId, - Roles = roles, - Permissions = permissions - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Targeting/TargetTypeFilter.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Targeting/TargetTypeFilter.cs deleted file mode 100644 index 6b8f43a..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Targeting/TargetTypeFilter.cs +++ /dev/null @@ -1,218 +0,0 @@ -using System.Text.Json; -using TakeoutSaaS.Domain.Tenants.Entities; - -namespace TakeoutSaaS.Application.App.Tenants.Targeting; - -/// -/// 目标受众过滤器。 -/// -public static class TargetTypeFilter -{ - private static readonly JsonSerializerOptions Options = new() - { - PropertyNameCaseInsensitive = true - }; - - /// - /// 判断公告是否匹配当前用户上下文。 - /// - /// 公告实体。 - /// 目标上下文。 - /// 是否匹配。 - public static bool IsMatch(TenantAnnouncement announcement, AnnouncementTargetContext context) - { - if (announcement == null) - { - return false; - } - - // 1. 租户端严格限制:公告必须属于当前租户 - if (announcement.TenantId != context.TenantId) - { - return false; - } - - var targetType = announcement.TargetType?.Trim(); - if (string.IsNullOrWhiteSpace(targetType)) - { - return true; - } - - var normalized = targetType.ToUpperInvariant(); - var parsed = TryParseParameters(announcement.TargetParameters, out var payload); - - return normalized switch - { - "ALL" or "ALL_TENANTS" or "TENANT_ALL" => ApplyPayloadConstraints(payload, parsed, context, allowEmpty: true), - "SPECIFIC_TENANTS" => RequireTenantMatch(payload, parsed, context) - && ApplyPayloadConstraints(payload, parsed, context, allowEmpty: false), - "USERS" or "SPECIFIC_USERS" or "USER_IDS" => RequireUserMatch(payload, parsed, context) - && ApplyPayloadConstraints(payload, parsed, context, allowEmpty: false), - "ROLES" or "ROLE" => RequireRoleMatch(payload, parsed, context) - && ApplyPayloadConstraints(payload, parsed, context, allowEmpty: false), - "PERMISSIONS" or "PERMISSION" => RequirePermissionMatch(payload, parsed, context) - && ApplyPayloadConstraints(payload, parsed, context, allowEmpty: false), - "MERCHANTS" or "MERCHANT_IDS" => RequireMerchantMatch(payload, parsed, context) - && ApplyPayloadConstraints(payload, parsed, context, allowEmpty: false), - _ => ApplyPayloadConstraints(payload, parsed, context, allowEmpty: false) - }; - } - - private static bool RequireTenantMatch(TargetParametersPayload payload, bool parsed, AnnouncementTargetContext context) - => parsed && payload.TenantIds is { Length: > 0 } && payload.TenantIds.Contains(context.TenantId); - - private static bool RequireUserMatch(TargetParametersPayload payload, bool parsed, AnnouncementTargetContext context) - => parsed && payload.UserIds is { Length: > 0 } && context.UserId != 0 && payload.UserIds.Contains(context.UserId); - - private static bool RequireMerchantMatch(TargetParametersPayload payload, bool parsed, AnnouncementTargetContext context) - => parsed && payload.MerchantIds is { Length: > 0 } && context.MerchantId.HasValue && payload.MerchantIds.Contains(context.MerchantId.Value); - - private static bool RequireRoleMatch(TargetParametersPayload payload, bool parsed, AnnouncementTargetContext context) - => parsed && payload.Roles is { Length: > 0 } && Intersects(payload.Roles, context.Roles); - - private static bool RequirePermissionMatch(TargetParametersPayload payload, bool parsed, AnnouncementTargetContext context) - => parsed && payload.Permissions is { Length: > 0 } && Intersects(payload.Permissions, context.Permissions); - - private static bool ApplyPayloadConstraints( - TargetParametersPayload payload, - bool parsed, - AnnouncementTargetContext context, - bool allowEmpty) - { - if (!parsed) - { - return false; - } - - if (!payload.HasConstraints) - { - return allowEmpty; - } - - if (payload.TenantIds is { Length: > 0 } && !payload.TenantIds.Contains(context.TenantId)) - { - return false; - } - - if (payload.UserIds is { Length: > 0 }) - { - if (context.UserId == 0 || !payload.UserIds.Contains(context.UserId)) - { - return false; - } - } - - if (payload.MerchantIds is { Length: > 0 }) - { - if (!context.MerchantId.HasValue || !payload.MerchantIds.Contains(context.MerchantId.Value)) - { - return false; - } - } - - if (payload.Roles is { Length: > 0 } && !Intersects(payload.Roles, context.Roles)) - { - return false; - } - - if (payload.Permissions is { Length: > 0 } && !Intersects(payload.Permissions, context.Permissions)) - { - return false; - } - - if (payload.Departments is { Length: > 0 } && !Intersects(payload.Departments, context.Departments)) - { - return false; - } - - return true; - } - - private static bool TryParseParameters(string? json, out TargetParametersPayload payload) - { - payload = new TargetParametersPayload(); - - if (string.IsNullOrWhiteSpace(json)) - { - return true; - } - - try - { - payload = JsonSerializer.Deserialize(json, Options) ?? new TargetParametersPayload(); - return true; - } - catch (JsonException) - { - return false; - } - } - - private static bool Intersects(IEnumerable left, IEnumerable right) - { - var set = new HashSet(right ?? Array.Empty(), StringComparer.OrdinalIgnoreCase); - foreach (var value in left ?? Array.Empty()) - { - if (set.Contains(value)) - { - return true; - } - } - - return false; - } - - private sealed class TargetParametersPayload - { - public long[]? TenantIds { get; init; } - public long[]? UserIds { get; init; } - public long[]? MerchantIds { get; init; } - public string[]? Roles { get; init; } - public string[]? Permissions { get; init; } - public string[]? Departments { get; init; } - - public bool HasConstraints - => (TenantIds?.Length ?? 0) > 0 - || (UserIds?.Length ?? 0) > 0 - || (MerchantIds?.Length ?? 0) > 0 - || (Roles?.Length ?? 0) > 0 - || (Permissions?.Length ?? 0) > 0 - || (Departments?.Length ?? 0) > 0; - } -} - -/// -/// 目标受众上下文。 -/// -public sealed record AnnouncementTargetContext -{ - /// - /// 租户 ID。 - /// - public long TenantId { get; init; } - - /// - /// 用户 ID。 - /// - public long UserId { get; init; } - - /// - /// 商户 ID(可选)。 - /// - public long? MerchantId { get; init; } - - /// - /// 角色集合。 - /// - public IReadOnlyCollection Roles { get; init; } = Array.Empty(); - - /// - /// 权限集合。 - /// - public IReadOnlyCollection Permissions { get; init; } = Array.Empty(); - - /// - /// 部门集合(可选)。 - /// - public IReadOnlyCollection Departments { get; init; } = Array.Empty(); -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Targeting/TenantAnnouncementTargetTypePolicy.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Targeting/TenantAnnouncementTargetTypePolicy.cs deleted file mode 100644 index 386328e..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Targeting/TenantAnnouncementTargetTypePolicy.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System.Collections.Frozen; - -namespace TakeoutSaaS.Application.App.Tenants.Targeting; - -/// -/// 租户公告目标受众类型策略(租户端)。 -/// -public static class TenantAnnouncementTargetTypePolicy -{ - private static readonly FrozenSet AllowedTargetTypes = FrozenSet.ToFrozenSet( - new[] - { - "ALL", - "TENANT_ALL", - "USERS", - "SPECIFIC_USERS", - "USER_IDS", - "ROLES", - "ROLE", - "PERMISSIONS", - "PERMISSION", - "MERCHANTS", - "MERCHANT_IDS" - }, - StringComparer.Ordinal); - - /// - /// 判断目标受众类型在租户端是否允许。 - /// - /// 目标受众类型。 - /// 允许返回 true,否则 false。 - public static bool IsAllowed(string? targetType) - { - if (string.IsNullOrWhiteSpace(targetType)) - { - return false; - } - - var normalized = Normalize(targetType); - return AllowedTargetTypes.Contains(normalized); - } - - /// - /// 规范化目标受众类型(Trim + UpperInvariant)。 - /// - /// 目标受众类型。 - /// 规范化后的类型。 - public static string Normalize(string targetType) => targetType.Trim().ToUpperInvariant(); -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/TenantMapping.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/TenantMapping.cs deleted file mode 100644 index 32d0d5f..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/TenantMapping.cs +++ /dev/null @@ -1,141 +0,0 @@ -using TakeoutSaaS.Application.App.Tenants.Dto; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; - -namespace TakeoutSaaS.Application.App.Tenants; - -/// -/// 租户 DTO 映射助手。 -/// -internal static class TenantMapping -{ - /// - /// 将租户认证实体映射为 DTO。 - /// - /// 认证实体。 - /// 认证 DTO 或 null。 - public static TenantVerificationDto? ToVerificationDto(this TenantVerificationProfile? profile) - => profile == null - ? null - : new TenantVerificationDto - { - Id = profile.Id, - TenantId = profile.TenantId, - Status = profile.Status, - BusinessLicenseNumber = profile.BusinessLicenseNumber, - BusinessLicenseUrl = profile.BusinessLicenseUrl, - LegalPersonName = profile.LegalPersonName, - LegalPersonIdNumber = profile.LegalPersonIdNumber, - LegalPersonIdFrontUrl = profile.LegalPersonIdFrontUrl, - LegalPersonIdBackUrl = profile.LegalPersonIdBackUrl, - BankAccountName = profile.BankAccountName, - BankAccountNumber = profile.BankAccountNumber, - BankName = profile.BankName, - AdditionalDataJson = profile.AdditionalDataJson, - SubmittedAt = profile.SubmittedAt, - ReviewRemarks = profile.ReviewRemarks, - ReviewedBy = profile.ReviewedBy, - ReviewedByName = profile.ReviewedByName, - ReviewedAt = profile.ReviewedAt - }; - - /// - /// 将套餐实体映射为 DTO。 - /// - /// 套餐实体。 - /// 套餐 DTO。 - public static TenantPackageDto ToDto(this TenantPackage package) - => new() - { - Id = package.Id, - Name = package.Name, - Description = package.Description, - PackageType = package.PackageType, - MonthlyPrice = package.MonthlyPrice, - YearlyPrice = package.YearlyPrice, - MaxStoreCount = package.MaxStoreCount, - MaxAccountCount = package.MaxAccountCount, - MaxStorageGb = package.MaxStorageGb, - MaxSmsCredits = package.MaxSmsCredits, - MaxDeliveryOrders = package.MaxDeliveryOrders, - FeaturePoliciesJson = package.FeaturePoliciesJson, - IsActive = package.IsActive, - IsPublicVisible = package.IsPublicVisible, - IsAllowNewTenantPurchase = package.IsAllowNewTenantPurchase, - PublishStatus = package.PublishStatus, - IsRecommended = package.IsRecommended, - Tags = package.Tags ?? [], - SortOrder = package.SortOrder - }; - - /// - /// 将账单实体映射为 DTO。 - /// - /// 账单实体。 - /// 账单 DTO。 - public static TenantBillingDto ToDto(this TenantBillingStatement bill) - => new() - { - Id = bill.Id, - TenantId = bill.TenantId, - StatementNo = bill.StatementNo, - PeriodStart = bill.PeriodStart, - PeriodEnd = bill.PeriodEnd, - AmountDue = bill.AmountDue, - AmountPaid = bill.AmountPaid, - Status = bill.Status, - DueDate = bill.DueDate, - LineItemsJson = bill.LineItemsJson - }; - - /// - /// 将公告实体映射为 DTO。 - /// - /// 公告实体。 - /// 是否已读。 - /// 阅读时间。 - /// 公告 DTO。 - public static TenantAnnouncementDto ToDto(this TenantAnnouncement announcement, bool isRead, DateTime? readAt) - => new() - { - Id = announcement.Id, - TenantId = announcement.TenantId, - Title = announcement.Title, - Content = announcement.Content, - AnnouncementType = announcement.AnnouncementType, - Priority = announcement.Priority, - EffectiveFrom = announcement.EffectiveFrom, - EffectiveTo = announcement.EffectiveTo, - PublisherScope = announcement.PublisherScope, - PublisherUserId = announcement.PublisherUserId, - Status = announcement.Status, - PublishedAt = announcement.PublishedAt, - RevokedAt = announcement.RevokedAt, - ScheduledPublishAt = announcement.ScheduledPublishAt, - TargetType = announcement.TargetType, - TargetParameters = announcement.TargetParameters, - RowVersion = announcement.RowVersion, - IsActive = announcement.Status == AnnouncementStatus.Published, - IsRead = isRead, - ReadAt = readAt - }; - - /// - /// 将通知实体映射为 DTO。 - /// - /// 通知实体。 - /// 通知 DTO。 - public static TenantNotificationDto ToDto(this TenantNotification notification) - => new() - { - Id = notification.Id, - TenantId = notification.TenantId, - Title = notification.Title, - Message = notification.Message, - Channel = notification.Channel, - Severity = notification.Severity, - SentAt = notification.SentAt, - ReadAt = notification.ReadAt, - MetadataJson = notification.MetadataJson - }; -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Validators/CreateAnnouncementCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Validators/CreateAnnouncementCommandValidator.cs deleted file mode 100644 index a1d1173..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Validators/CreateAnnouncementCommandValidator.cs +++ /dev/null @@ -1,45 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Tenants.Commands; -using TakeoutSaaS.Application.App.Tenants.Targeting; -using TakeoutSaaS.Domain.Tenants.Enums; - -namespace TakeoutSaaS.Application.App.Tenants.Validators; - -/// -/// 创建公告命令验证器。 -/// -public sealed class CreateAnnouncementCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public CreateAnnouncementCommandValidator() - { - RuleFor(x => x.Title) - .NotEmpty() - .MaximumLength(128); - - RuleFor(x => x.Content) - .NotEmpty(); - - RuleFor(x => x.TargetType) - .NotEmpty(); - // 1. (空行后) 限制租户端目标类型,禁止跨租户目标 - RuleFor(x => x.TargetType) - .Must(TenantAnnouncementTargetTypePolicy.IsAllowed) - .WithMessage("租户端不支持该目标受众类型"); - - RuleFor(x => x.TenantId) - .GreaterThan(0) - .WithMessage("TenantId 必须大于 0"); - - RuleFor(x => x.PublisherScope) - .Equal(PublisherScope.Tenant) - .WithMessage("租户端仅允许创建租户公告"); - - RuleFor(x => x.EffectiveFrom) - .LessThan(x => x.EffectiveTo!.Value) - .When(x => x.EffectiveTo.HasValue) - .WithMessage("生效开始时间必须早于结束时间"); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Validators/GetTenantQuotaUsageHistoryQueryValidator.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Validators/GetTenantQuotaUsageHistoryQueryValidator.cs deleted file mode 100644 index 49ea98c..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Validators/GetTenantQuotaUsageHistoryQueryValidator.cs +++ /dev/null @@ -1,27 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Tenants.Queries; - -namespace TakeoutSaaS.Application.App.Tenants.Validators; - -/// -/// 租户配额使用历史查询验证器。 -/// -public sealed class GetTenantQuotaUsageHistoryQueryValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public GetTenantQuotaUsageHistoryQueryValidator() - { - RuleFor(x => x.TenantId).GreaterThan(0); - RuleFor(x => x.Page).GreaterThanOrEqualTo(1); - RuleFor(x => x.PageSize).InclusiveBetween(1, 100); - - // 时间范围校验 - When(x => x.StartDate.HasValue && x.EndDate.HasValue, () => - { - RuleFor(x => x.EndDate!.Value).GreaterThanOrEqualTo(x => x.StartDate!.Value); - }); - } -} - diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Validators/PublishAnnouncementCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Validators/PublishAnnouncementCommandValidator.cs deleted file mode 100644 index fa32af4..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Validators/PublishAnnouncementCommandValidator.cs +++ /dev/null @@ -1,24 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Tenants.Commands; - -namespace TakeoutSaaS.Application.App.Tenants.Validators; - -/// -/// 发布公告命令验证器。 -/// -public sealed class PublishAnnouncementCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public PublishAnnouncementCommandValidator() - { - RuleFor(x => x.AnnouncementId) - .GreaterThan(0); - - RuleFor(x => x.RowVersion) - .NotNull() - .Must(rowVersion => rowVersion != null && rowVersion.Length > 0) - .WithMessage("RowVersion 不能为空"); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Validators/RevokeAnnouncementCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Validators/RevokeAnnouncementCommandValidator.cs deleted file mode 100644 index ab4580a..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Validators/RevokeAnnouncementCommandValidator.cs +++ /dev/null @@ -1,24 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Tenants.Commands; - -namespace TakeoutSaaS.Application.App.Tenants.Validators; - -/// -/// 撤销公告命令验证器。 -/// -public sealed class RevokeAnnouncementCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public RevokeAnnouncementCommandValidator() - { - RuleFor(x => x.AnnouncementId) - .GreaterThan(0); - - RuleFor(x => x.RowVersion) - .NotNull() - .Must(rowVersion => rowVersion != null && rowVersion.Length > 0) - .WithMessage("RowVersion 不能为空"); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Validators/SelfRegisterTenantCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Validators/SelfRegisterTenantCommandValidator.cs deleted file mode 100644 index 411d834..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Validators/SelfRegisterTenantCommandValidator.cs +++ /dev/null @@ -1,22 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Tenants.Commands; - -namespace TakeoutSaaS.Application.App.Tenants.Validators; - -/// -/// 自助注册租户命令验证器。 -/// -public sealed class SelfRegisterTenantCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public SelfRegisterTenantCommandValidator() - { - RuleFor(x => x.AdminAccount) - .NotEmpty() - .MaximumLength(64) - .Matches("^[A-Za-z0-9]+$") - .WithMessage("登录账号仅允许大小写字母和数字"); - } -} diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Validators/UpdateAnnouncementCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Validators/UpdateAnnouncementCommandValidator.cs deleted file mode 100644 index 211a5aa..0000000 --- a/src/Application/TakeoutSaaS.Application/App/Tenants/Validators/UpdateAnnouncementCommandValidator.cs +++ /dev/null @@ -1,34 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.App.Tenants.Commands; -using TakeoutSaaS.Application.App.Tenants.Targeting; - -namespace TakeoutSaaS.Application.App.Tenants.Validators; - -/// -/// 更新公告命令验证器。 -/// -public sealed class UpdateAnnouncementCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public UpdateAnnouncementCommandValidator() - { - RuleFor(x => x.Title) - .NotEmpty() - .MaximumLength(128); - - RuleFor(x => x.Content) - .NotEmpty(); - - RuleFor(x => x.TargetType) - .NotEmpty() - .Must(TenantAnnouncementTargetTypePolicy.IsAllowed) - .WithMessage("租户端不支持该目标受众类型"); - - RuleFor(x => x.RowVersion) - .NotNull() - .Must(rowVersion => rowVersion != null && rowVersion.Length > 0) - .WithMessage("RowVersion 不能为空"); - } -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Abstractions/ICsvDictionaryParser.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Abstractions/ICsvDictionaryParser.cs deleted file mode 100644 index 6b206b2..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Abstractions/ICsvDictionaryParser.cs +++ /dev/null @@ -1,17 +0,0 @@ -using TakeoutSaaS.Application.Dictionary.Models; - -namespace TakeoutSaaS.Application.Dictionary.Abstractions; - -/// -/// CSV 字典导入解析器。 -/// -public interface ICsvDictionaryParser -{ - /// - /// 解析 CSV 数据。 - /// - /// 输入流。 - /// 取消标记。 - /// 解析后的记录列表。 - Task> ParseAsync(Stream stream, CancellationToken cancellationToken = default); -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Abstractions/IDictionaryAppService.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Abstractions/IDictionaryAppService.cs deleted file mode 100644 index 60e5f61..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Abstractions/IDictionaryAppService.cs +++ /dev/null @@ -1,26 +0,0 @@ -using TakeoutSaaS.Application.Dictionary.Contracts; -using TakeoutSaaS.Application.Dictionary.Models; - -namespace TakeoutSaaS.Application.Dictionary.Abstractions; - -/// -/// 参数字典应用服务接口。 -/// -public interface IDictionaryAppService -{ - Task CreateGroupAsync(CreateDictionaryGroupRequest request, CancellationToken cancellationToken = default); - - Task UpdateGroupAsync(long groupId, UpdateDictionaryGroupRequest request, CancellationToken cancellationToken = default); - - Task DeleteGroupAsync(long groupId, CancellationToken cancellationToken = default); - - Task> SearchGroupsAsync(DictionaryGroupQuery request, CancellationToken cancellationToken = default); - - Task CreateItemAsync(CreateDictionaryItemRequest request, CancellationToken cancellationToken = default); - - Task UpdateItemAsync(long itemId, UpdateDictionaryItemRequest request, CancellationToken cancellationToken = default); - - Task DeleteItemAsync(long itemId, CancellationToken cancellationToken = default); - - Task>> GetCachedItemsAsync(DictionaryBatchQueryRequest request, CancellationToken cancellationToken = default); -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Abstractions/IDictionaryCache.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Abstractions/IDictionaryCache.cs deleted file mode 100644 index f9ea54b..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Abstractions/IDictionaryCache.cs +++ /dev/null @@ -1,24 +0,0 @@ -using TakeoutSaaS.Application.Dictionary.Models; - -namespace TakeoutSaaS.Application.Dictionary.Abstractions; - -/// -/// 字典缓存读写接口。 -/// -public interface IDictionaryCache -{ - /// - /// 获取缓存。 - /// - Task?> GetAsync(long tenantId, string code, CancellationToken cancellationToken = default); - - /// - /// 写入缓存。 - /// - Task SetAsync(long tenantId, string code, IReadOnlyList items, CancellationToken cancellationToken = default); - - /// - /// 移除缓存。 - /// - Task RemoveAsync(long tenantId, string code, CancellationToken cancellationToken = default); -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Abstractions/IDictionaryHybridCache.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Abstractions/IDictionaryHybridCache.cs deleted file mode 100644 index 8a4c736..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Abstractions/IDictionaryHybridCache.cs +++ /dev/null @@ -1,26 +0,0 @@ -using TakeoutSaaS.Domain.Dictionary.Enums; - -namespace TakeoutSaaS.Application.Dictionary.Abstractions; - -/// -/// 字典两级缓存访问接口。 -/// -public interface IDictionaryHybridCache -{ - /// - /// 读取缓存,不存在时通过工厂生成并回填。 - /// - Task GetOrCreateAsync( - string key, - TimeSpan ttl, - Func> factory, - CancellationToken cancellationToken = default); - - /// - /// 按前缀失效缓存。 - /// - Task InvalidateAsync( - string prefix, - CacheInvalidationOperation operation = CacheInvalidationOperation.Update, - CancellationToken cancellationToken = default); -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Abstractions/IJsonDictionaryParser.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Abstractions/IJsonDictionaryParser.cs deleted file mode 100644 index 990639f..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Abstractions/IJsonDictionaryParser.cs +++ /dev/null @@ -1,17 +0,0 @@ -using TakeoutSaaS.Application.Dictionary.Models; - -namespace TakeoutSaaS.Application.Dictionary.Abstractions; - -/// -/// JSON 字典导入解析器。 -/// -public interface IJsonDictionaryParser -{ - /// - /// 解析 JSON 数据。 - /// - /// 输入流。 - /// 取消标记。 - /// 解析后的记录列表。 - Task> ParseAsync(Stream stream, CancellationToken cancellationToken = default); -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Contracts/CreateDictionaryGroupRequest.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Contracts/CreateDictionaryGroupRequest.cs deleted file mode 100644 index 17de073..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Contracts/CreateDictionaryGroupRequest.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using TakeoutSaaS.Domain.Dictionary.Enums; - -namespace TakeoutSaaS.Application.Dictionary.Contracts; - -/// -/// 创建字典分组请求。 -/// -public sealed class CreateDictionaryGroupRequest -{ - /// - /// 分组编码。 - /// - [Required, MaxLength(64)] - public string Code { get; set; } = string.Empty; - - /// - /// 分组名称。 - /// - [Required, MaxLength(128)] - public string Name { get; set; } = string.Empty; - - /// - /// 作用域:系统/业务。 - /// - [Required] - public DictionaryScope Scope { get; set; } = DictionaryScope.Business; - - /// - /// 是否允许租户覆盖。 - /// - public bool AllowOverride { get; set; } - - /// - /// 描述信息。 - /// - [MaxLength(512)] - public string? Description { get; set; } -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Contracts/CreateDictionaryItemRequest.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Contracts/CreateDictionaryItemRequest.cs deleted file mode 100644 index bcd5c4e..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Contracts/CreateDictionaryItemRequest.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using System.Text.Json.Serialization; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.Dictionary.Contracts; - -/// -/// 创建字典项请求。 -/// -public sealed class CreateDictionaryItemRequest -{ - /// - /// 所属分组 ID。 - /// - [Required] - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long GroupId { get; set; } - - /// - /// 字典项键。 - /// - [Required, MaxLength(128)] - public string Key { get; set; } = string.Empty; - - /// - /// 字典项值。 - /// - [Required] - public Dictionary Value { get; set; } = new(StringComparer.OrdinalIgnoreCase); - - /// - /// 是否默认项。 - /// - public bool IsDefault { get; set; } - - /// - /// 是否启用。 - /// - public bool IsEnabled { get; set; } = true; - - /// - /// 排序值。 - /// - public int SortOrder { get; set; } = 100; - - /// - /// 描述信息。 - /// - [MaxLength(512)] - public string? Description { get; set; } -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Contracts/DictionaryBatchQueryRequest.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Contracts/DictionaryBatchQueryRequest.cs deleted file mode 100644 index cc5e2c6..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Contracts/DictionaryBatchQueryRequest.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Application.Dictionary.Contracts; - -/// -/// 批量查询字典项请求。 -/// -public sealed class DictionaryBatchQueryRequest -{ - /// - /// 分组编码集合。 - /// - [Required] - public IReadOnlyCollection Codes { get; init; } = Array.Empty(); -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Contracts/DictionaryGroupQuery.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Contracts/DictionaryGroupQuery.cs deleted file mode 100644 index c7afa74..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Contracts/DictionaryGroupQuery.cs +++ /dev/null @@ -1,49 +0,0 @@ -using TakeoutSaaS.Domain.Dictionary.Enums; - -namespace TakeoutSaaS.Application.Dictionary.Contracts; - -/// -/// 字典分组查询参数。 -/// -public sealed class DictionaryGroupQuery -{ - /// - /// 作用域过滤。 - /// - public DictionaryScope? Scope { get; set; } - - /// - /// 关键字(匹配编码或名称)。 - /// - public string? Keyword { get; set; } - - /// - /// 启用状态过滤。 - /// - public bool? IsEnabled { get; set; } - - /// - /// 分页页码。 - /// - public int Page { get; set; } = 1; - - /// - /// 分页大小。 - /// - public int PageSize { get; set; } = 20; - - /// - /// 排序字段。 - /// - public string? SortBy { get; set; } - - /// - /// 排序方向(asc/desc)。 - /// - public string? SortOrder { get; set; } - - /// - /// 是否包含字典项。 - /// - public bool IncludeItems { get; set; } -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Contracts/DictionaryImportRequest.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Contracts/DictionaryImportRequest.cs deleted file mode 100644 index 76d69b7..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Contracts/DictionaryImportRequest.cs +++ /dev/null @@ -1,34 +0,0 @@ -using TakeoutSaaS.Domain.Dictionary.Enums; - -namespace TakeoutSaaS.Application.Dictionary.Contracts; - -/// -/// 字典导入请求。 -/// -public sealed class DictionaryImportRequest -{ - /// - /// 分组 ID。 - /// - public long GroupId { get; init; } - - /// - /// 文件名称。 - /// - public string FileName { get; init; } = string.Empty; - - /// - /// 文件大小(字节)。 - /// - public long FileSize { get; init; } - - /// - /// 冲突解决模式。 - /// - public ConflictResolutionMode ConflictMode { get; init; } = ConflictResolutionMode.Skip; - - /// - /// 文件流。 - /// - public Stream FileStream { get; init; } = Stream.Null; -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Contracts/DictionaryOverrideHiddenItemsRequest.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Contracts/DictionaryOverrideHiddenItemsRequest.cs deleted file mode 100644 index dd92927..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Contracts/DictionaryOverrideHiddenItemsRequest.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Application.Dictionary.Contracts; - -/// -/// 更新字典覆盖隐藏项请求。 -/// -public sealed class DictionaryOverrideHiddenItemsRequest -{ - /// - /// 需要隐藏的系统字典项 ID 列表。 - /// - [Required] - public long[] HiddenItemIds { get; set; } = Array.Empty(); -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Contracts/DictionaryOverrideSortOrderRequest.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Contracts/DictionaryOverrideSortOrderRequest.cs deleted file mode 100644 index cb7eabf..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Contracts/DictionaryOverrideSortOrderRequest.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Application.Dictionary.Contracts; - -/// -/// 更新字典覆盖排序请求。 -/// -public sealed class DictionaryOverrideSortOrderRequest -{ - /// - /// 排序配置(字典项 ID -> 排序值)。 - /// - [Required] - public Dictionary SortOrder { get; set; } = new(); -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Contracts/UpdateDictionaryGroupRequest.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Contracts/UpdateDictionaryGroupRequest.cs deleted file mode 100644 index 8c66b3a..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Contracts/UpdateDictionaryGroupRequest.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Application.Dictionary.Contracts; - -/// -/// 更新字典分组请求。 -/// -public sealed class UpdateDictionaryGroupRequest -{ - /// - /// 分组名称。 - /// - [Required, MaxLength(128)] - public string Name { get; set; } = string.Empty; - - /// - /// 描述信息。 - /// - [MaxLength(512)] - public string? Description { get; set; } - - /// - /// 是否允许租户覆盖。 - /// - public bool AllowOverride { get; set; } - - /// - /// 是否启用。 - /// - public bool IsEnabled { get; set; } = true; - - /// - /// 行版本,用于并发控制。 - /// - public byte[]? RowVersion { get; set; } -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Contracts/UpdateDictionaryItemRequest.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Contracts/UpdateDictionaryItemRequest.cs deleted file mode 100644 index b2d00f5..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Contracts/UpdateDictionaryItemRequest.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Application.Dictionary.Contracts; - -/// -/// 更新字典项请求。 -/// -public sealed class UpdateDictionaryItemRequest -{ - /// - /// 字典项键。 - /// - [Required, MaxLength(128)] - public string Key { get; set; } = string.Empty; - - /// - /// 字典项值。 - /// - [Required] - public Dictionary Value { get; set; } = new(StringComparer.OrdinalIgnoreCase); - - /// - /// 是否默认项。 - /// - public bool IsDefault { get; set; } - - /// - /// 是否启用。 - /// - public bool IsEnabled { get; set; } = true; - - /// - /// 排序值。 - /// - public int SortOrder { get; set; } = 100; - - /// - /// 描述信息。 - /// - [MaxLength(512)] - public string? Description { get; set; } - - /// - /// 行版本,用于并发控制。 - /// - public byte[]? RowVersion { get; set; } -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Extensions/DictionaryServiceCollectionExtensions.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Extensions/DictionaryServiceCollectionExtensions.cs deleted file mode 100644 index 1e2f972..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Extensions/DictionaryServiceCollectionExtensions.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using TakeoutSaaS.Application.Dictionary.Abstractions; -using TakeoutSaaS.Application.Dictionary.Services; - -namespace TakeoutSaaS.Application.Dictionary.Extensions; - -/// -/// 字典应用服务注册扩展。 -/// -public static class DictionaryServiceCollectionExtensions -{ - /// - /// 注册字典模块应用层组件。 - /// - public static IServiceCollection AddDictionaryApplication(this IServiceCollection services) - { - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - return services; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Models/DictionaryGroupDto.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Models/DictionaryGroupDto.cs deleted file mode 100644 index 8fb64fc..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Models/DictionaryGroupDto.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Dictionary.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.Dictionary.Models; - -/// -/// 字典分组 DTO。 -/// -public sealed class DictionaryGroupDto -{ - /// - /// 分组 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 分组编码。 - /// - public string Code { get; init; } = string.Empty; - - /// - /// 租户 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 分组名称。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 字典作用域。 - /// - public DictionaryScope Scope { get; init; } - - /// - /// 描述。 - /// - public string? Description { get; init; } - - /// - /// 是否允许覆盖。 - /// - public bool AllowOverride { get; init; } - - /// - /// 是否启用。 - /// - public bool IsEnabled { get; init; } - - /// - /// 创建时间(UTC)。 - /// - public DateTime CreatedAt { get; init; } - - /// - /// 更新时间(UTC)。 - /// - public DateTime? UpdatedAt { get; init; } - - /// - /// 并发控制字段。 - /// - public byte[] RowVersion { get; init; } = Array.Empty(); - - /// - /// 字典项集合。 - /// - public IReadOnlyList Items { get; init; } = Array.Empty(); -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Models/DictionaryImportResultDto.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Models/DictionaryImportResultDto.cs deleted file mode 100644 index e1ddbe5..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Models/DictionaryImportResultDto.cs +++ /dev/null @@ -1,53 +0,0 @@ -namespace TakeoutSaaS.Application.Dictionary.Models; - -/// -/// 字典导入结果 DTO。 -/// -public sealed class DictionaryImportResultDto -{ - /// - /// 成功数量。 - /// - public int SuccessCount { get; init; } - - /// - /// 跳过数量。 - /// - public int SkipCount { get; init; } - - /// - /// 错误数量。 - /// - public int ErrorCount { get; init; } - - /// - /// 错误列表。 - /// - public IReadOnlyList Errors { get; init; } = Array.Empty(); - - /// - /// 处理耗时。 - /// - public TimeSpan Duration { get; init; } - - /// - /// 导入错误详情。 - /// - public sealed class ImportError - { - /// - /// 行号。 - /// - public int RowNumber { get; init; } - - /// - /// 字段名。 - /// - public string Field { get; init; } = string.Empty; - - /// - /// 错误信息。 - /// - public string Message { get; init; } = string.Empty; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Models/DictionaryImportRow.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Models/DictionaryImportRow.cs deleted file mode 100644 index c6039b1..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Models/DictionaryImportRow.cs +++ /dev/null @@ -1,47 +0,0 @@ -namespace TakeoutSaaS.Application.Dictionary.Models; - -/// -/// 字典导入记录。 -/// -public sealed class DictionaryImportRow -{ - /// - /// 行号(从 1 开始,包含表头行的偏移)。 - /// - public int RowNumber { get; init; } - - /// - /// 字典分组编码。 - /// - public string? Code { get; init; } - - /// - /// 字典项键。 - /// - public string? Key { get; init; } - - /// - /// 字典项值(JSON 字符串)。 - /// - public string? Value { get; init; } - - /// - /// 排序值。 - /// - public int? SortOrder { get; init; } - - /// - /// 是否启用。 - /// - public bool? IsEnabled { get; init; } - - /// - /// 描述。 - /// - public string? Description { get; init; } - - /// - /// 来源:system / tenant。 - /// - public string? Source { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Models/DictionaryItemDto.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Models/DictionaryItemDto.cs deleted file mode 100644 index 36a56c8..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Models/DictionaryItemDto.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.Dictionary.Models; - -/// -/// 字典项 DTO。 -/// -public sealed class DictionaryItemDto -{ - /// - /// 字典项 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 分组 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long GroupId { get; init; } - - /// - /// 键。 - /// - public string Key { get; init; } = string.Empty; - - /// - /// 值。 - /// - [JsonPropertyName("value")] - public Dictionary Value { get; init; } = new(StringComparer.OrdinalIgnoreCase); - - /// - /// 是否默认值。 - /// - public bool IsDefault { get; init; } - - /// - /// 是否启用。 - /// - public bool IsEnabled { get; init; } - - /// - /// 排序序号。 - /// - public int SortOrder { get; init; } - - /// - /// 描述。 - /// - public string? Description { get; init; } - - /// - /// 来源:system / tenant。 - /// - public string Source { get; init; } = "system"; - - /// - /// 并发控制字段。 - /// - public byte[] RowVersion { get; init; } = Array.Empty(); -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Models/LabelOverrideDto.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Models/LabelOverrideDto.cs deleted file mode 100644 index 7a48697..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Models/LabelOverrideDto.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Domain.Dictionary.Enums; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.Dictionary.Models; - -/// -/// 字典标签覆盖 DTO。 -/// -public sealed class LabelOverrideDto -{ - /// - /// 覆盖记录 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long Id { get; init; } - - /// - /// 租户 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 被覆盖的字典项 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long DictionaryItemId { get; init; } - - /// - /// 字典项 Key。 - /// - public string DictionaryItemKey { get; init; } = string.Empty; - - /// - /// 原始显示值(多语言)。 - /// - public Dictionary OriginalValue { get; init; } = new(StringComparer.OrdinalIgnoreCase); - - /// - /// 覆盖后的显示值(多语言)。 - /// - public Dictionary OverrideValue { get; init; } = new(StringComparer.OrdinalIgnoreCase); - - /// - /// 覆盖类型。 - /// - public OverrideType OverrideType { get; init; } - - /// - /// 覆盖类型名称。 - /// - public string OverrideTypeName => OverrideType switch - { - OverrideType.TenantCustomization => "租户定制", - _ => "未知" - }; - - /// - /// 覆盖原因/备注。 - /// - public string? Reason { get; init; } - - /// - /// 创建时间。 - /// - public DateTime CreatedAt { get; init; } - - /// - /// 更新时间。 - /// - public DateTime? UpdatedAt { get; init; } - - /// - /// 创建人 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long? CreatedBy { get; init; } - - /// - /// 更新人 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long? UpdatedBy { get; init; } -} - -/// -/// 创建/更新标签覆盖请求。 -/// -public sealed class UpsertLabelOverrideRequest -{ - /// - /// 被覆盖的字典项 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long DictionaryItemId { get; init; } - - /// - /// 覆盖后的显示值(多语言)。 - /// - public Dictionary OverrideValue { get; init; } = new(StringComparer.OrdinalIgnoreCase); - - /// - /// 覆盖原因/备注。 - /// - public string? Reason { get; init; } -} - -/// -/// 批量覆盖请求。 -/// -public sealed class BatchLabelOverrideRequest -{ - /// - /// 覆盖项列表。 - /// - public List Items { get; init; } = new(); -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Models/OverrideConfigDto.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Models/OverrideConfigDto.cs deleted file mode 100644 index 574e800..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Models/OverrideConfigDto.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Text.Json.Serialization; -using TakeoutSaaS.Shared.Abstractions.Serialization; - -namespace TakeoutSaaS.Application.Dictionary.Models; - -/// -/// 租户字典覆盖配置 DTO。 -/// -public sealed class OverrideConfigDto -{ - /// - /// 租户 ID。 - /// - [JsonConverter(typeof(SnowflakeIdJsonConverter))] - public long TenantId { get; init; } - - /// - /// 系统字典分组编码。 - /// - public string SystemDictionaryGroupCode { get; init; } = string.Empty; - - /// - /// 是否启用覆盖。 - /// - public bool OverrideEnabled { get; init; } - - /// - /// 隐藏的系统字典项 ID 列表。 - /// - public long[] HiddenSystemItemIds { get; init; } = Array.Empty(); - - /// - /// 自定义排序映射。 - /// - public Dictionary CustomSortOrder { get; init; } = new(); -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryAppService.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryAppService.cs deleted file mode 100644 index 4001b0a..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryAppService.cs +++ /dev/null @@ -1,459 +0,0 @@ -using Microsoft.Extensions.Logging; -using System.Security.Cryptography; -using TakeoutSaaS.Application.Dictionary.Abstractions; -using TakeoutSaaS.Application.Dictionary.Contracts; -using TakeoutSaaS.Application.Dictionary.Models; -using TakeoutSaaS.Domain.Dictionary.Entities; -using TakeoutSaaS.Domain.Dictionary.Enums; -using TakeoutSaaS.Domain.Dictionary.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Dictionary.Services; - -/// -/// 参数字典应用服务实现。 -/// -public sealed class DictionaryAppService( - IDictionaryRepository repository, - IDictionaryCache cache, - ITenantProvider tenantProvider, - ILogger logger) : IDictionaryAppService -{ - /// - /// 创建字典分组。 - /// - /// 创建请求。 - /// 取消标记。 - /// 分组 DTO。 - public async Task CreateGroupAsync(CreateDictionaryGroupRequest request, CancellationToken cancellationToken = default) - { - // 1. 规范化编码并确定租户 - var normalizedCode = NormalizeCode(request.Code); - var targetTenant = ResolveTargetTenant(request.Scope); - - // 2. 校验编码唯一 - var existing = await repository.FindGroupByCodeAsync(normalizedCode, cancellationToken); - if (existing != null) - { - throw new BusinessException(ErrorCodes.Conflict, $"字典分组编码 {normalizedCode} 已存在"); - } - - // 3. 构建分组实体 - var group = new DictionaryGroup - { - Id = 0, - TenantId = targetTenant, - Code = normalizedCode, - Name = request.Name.Trim(), - Scope = request.Scope, - AllowOverride = request.AllowOverride, - Description = request.Description?.Trim(), - IsEnabled = true, - RowVersion = RandomNumberGenerator.GetBytes(16) - }; - - // 4. 持久化并返回 - await repository.AddGroupAsync(group, cancellationToken); - await repository.SaveChangesAsync(cancellationToken); - logger.LogInformation("创建字典分组:{Code}({Scope})", group.Code, group.Scope); - return MapGroup(group, includeItems: false); - } - - /// - /// 更新字典分组。 - /// - /// 分组 ID。 - /// 更新请求。 - /// 取消标记。 - /// 分组 DTO。 - public async Task UpdateGroupAsync(long groupId, UpdateDictionaryGroupRequest request, CancellationToken cancellationToken = default) - { - // 1. 读取分组并校验权限 - var group = await RequireGroupAsync(groupId, cancellationToken); - EnsureScopePermission(group.Scope); - - if (request.RowVersion == null || request.RowVersion.Length == 0) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "RowVersion 不能为空"); - } - - if (!request.RowVersion.SequenceEqual(group.RowVersion)) - { - throw new BusinessException(ErrorCodes.Conflict, "字典分组已被修改,请刷新后重试"); - } - - // 2. 更新字段 - group.Name = request.Name.Trim(); - group.Description = request.Description?.Trim(); - group.IsEnabled = request.IsEnabled; - group.AllowOverride = request.AllowOverride; - group.RowVersion = RandomNumberGenerator.GetBytes(16); - - // 3. 持久化并失效缓存 - try - { - await repository.SaveChangesAsync(cancellationToken); - } - catch (Exception exception) when (IsConcurrencyException(exception)) - { - throw new BusinessException(ErrorCodes.Conflict, "字典分组已被修改,请刷新后重试"); - } - await InvalidateCacheAsync(group, cancellationToken); - logger.LogInformation("更新字典分组:{GroupId}", group.Id); - return MapGroup(group, includeItems: false); - } - - /// - /// 删除字典分组。 - /// - /// 分组 ID。 - /// 取消标记。 - public async Task DeleteGroupAsync(long groupId, CancellationToken cancellationToken = default) - { - // 1. 读取分组并校验权限 - var group = await RequireGroupAsync(groupId, cancellationToken); - EnsureScopePermission(group.Scope); - - // 2. 删除并失效缓存 - await repository.RemoveGroupAsync(group, cancellationToken); - await repository.SaveChangesAsync(cancellationToken); - await InvalidateCacheAsync(group, cancellationToken); - logger.LogInformation("删除字典分组:{GroupId}", group.Id); - } - - /// - /// 搜索字典分组。 - /// - /// 查询条件。 - /// 取消标记。 - /// 分组列表。 - public async Task> SearchGroupsAsync(DictionaryGroupQuery request, CancellationToken cancellationToken = default) - { - // 1. 确定查询范围并校验权限 - var tenantId = tenantProvider.GetCurrentTenantId(); - var scope = ResolveScopeForQuery(request.Scope, tenantId); - EnsureScopePermission(scope); - - // 2. 查询分组及可选项 - var groups = await repository.SearchGroupsAsync(scope, cancellationToken); - var includeItems = request.IncludeItems; - var result = new List(groups.Count); - - foreach (var group in groups) - { - IReadOnlyList items = Array.Empty(); - if (includeItems) - { - // 查询分组下字典项 - var itemEntities = await repository.GetItemsByGroupIdAsync(group.Id, cancellationToken); - items = itemEntities.Select(MapItem).ToList(); - } - - result.Add(MapGroup(group, includeItems, items)); - } - - return result; - } - - /// - /// 创建字典项。 - /// - /// 创建请求。 - /// 取消标记。 - /// 字典项 DTO。 - public async Task CreateItemAsync(CreateDictionaryItemRequest request, CancellationToken cancellationToken = default) - { - // 1. 校验分组与权限 - var group = await RequireGroupAsync(request.GroupId, cancellationToken); - EnsureScopePermission(group.Scope); - - // 2. 构建字典项 - var item = new DictionaryItem - { - Id = 0, - TenantId = group.TenantId, - GroupId = group.Id, - Key = request.Key.Trim(), - Value = DictionaryValueConverter.Serialize(request.Value), - Description = request.Description?.Trim(), - SortOrder = request.SortOrder, - IsDefault = request.IsDefault, - IsEnabled = request.IsEnabled, - RowVersion = RandomNumberGenerator.GetBytes(16) - }; - - // 3. 持久化并失效缓存 - await repository.AddItemAsync(item, cancellationToken); - await repository.SaveChangesAsync(cancellationToken); - await InvalidateCacheAsync(group, cancellationToken); - logger.LogInformation("新增字典项:{ItemId}", item.Id); - return MapItem(item); - } - - /// - /// 更新字典项。 - /// - /// 字典项 ID。 - /// 更新请求。 - /// 取消标记。 - /// 字典项 DTO。 - public async Task UpdateItemAsync(long itemId, UpdateDictionaryItemRequest request, CancellationToken cancellationToken = default) - { - // 1. 读取字典项与分组并校验权限 - var item = await RequireItemAsync(itemId, cancellationToken); - var group = await RequireGroupAsync(item.GroupId, cancellationToken); - EnsureScopePermission(group.Scope); - - if (request.RowVersion == null || request.RowVersion.Length == 0) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "RowVersion 不能为空"); - } - - if (!request.RowVersion.SequenceEqual(item.RowVersion)) - { - throw new BusinessException(ErrorCodes.Conflict, "字典项已被修改,请刷新后重试"); - } - - // 2. 更新字段 - item.Key = request.Key.Trim(); - item.Value = DictionaryValueConverter.Serialize(request.Value); - item.Description = request.Description?.Trim(); - item.SortOrder = request.SortOrder; - item.IsDefault = request.IsDefault; - item.IsEnabled = request.IsEnabled; - item.RowVersion = RandomNumberGenerator.GetBytes(16); - - // 3. 持久化并失效缓存 - try - { - await repository.SaveChangesAsync(cancellationToken); - } - catch (Exception exception) when (IsConcurrencyException(exception)) - { - throw new BusinessException(ErrorCodes.Conflict, "字典项已被修改,请刷新后重试"); - } - await InvalidateCacheAsync(group, cancellationToken); - logger.LogInformation("更新字典项:{ItemId}", item.Id); - return MapItem(item); - } - - /// - /// 删除字典项。 - /// - /// 字典项 ID。 - /// 取消标记。 - public async Task DeleteItemAsync(long itemId, CancellationToken cancellationToken = default) - { - // 1. 读取字典项与分组并校验权限 - var item = await RequireItemAsync(itemId, cancellationToken); - var group = await RequireGroupAsync(item.GroupId, cancellationToken); - EnsureScopePermission(group.Scope); - - // 2. 删除并失效缓存 - await repository.RemoveItemAsync(item, cancellationToken); - await repository.SaveChangesAsync(cancellationToken); - await InvalidateCacheAsync(group, cancellationToken); - logger.LogInformation("删除字典项:{ItemId}", item.Id); - } - - /// - /// 批量获取缓存中的字典项。 - /// - /// 批量查询请求。 - /// 取消标记。 - /// 按编码分组的字典项集合。 - public async Task>> GetCachedItemsAsync(DictionaryBatchQueryRequest request, CancellationToken cancellationToken = default) - { - // 1. 规范化编码 - var normalizedCodes = request.Codes - .Where(code => !string.IsNullOrWhiteSpace(code)) - .Select(NormalizeCode) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToArray(); - - if (normalizedCodes.Length == 0) - { - return new Dictionary>(StringComparer.OrdinalIgnoreCase); - } - - // 2. 按租户合并系统与业务字典 - var tenantId = tenantProvider.GetCurrentTenantId(); - var result = new Dictionary>(StringComparer.OrdinalIgnoreCase); - - foreach (var code in normalizedCodes) - { - var systemItems = await GetOrLoadCacheAsync(0, code, cancellationToken); - if (tenantId == 0) - { - result[code] = systemItems; - continue; - } - - var tenantItems = await GetOrLoadCacheAsync(tenantId, code, cancellationToken); - result[code] = MergeItems(systemItems, tenantItems); - } - - return result; - } - - private async Task RequireGroupAsync(long groupId, CancellationToken cancellationToken) - { - // 1. 读取分组,找不到抛异常 - var group = await repository.FindGroupByIdAsync(groupId, cancellationToken); - if (group == null) - { - throw new BusinessException(ErrorCodes.NotFound, "字典分组不存在"); - } - - return group; - } - - private async Task RequireItemAsync(long itemId, CancellationToken cancellationToken) - { - // 1. 读取字典项,找不到抛异常 - var item = await repository.FindItemByIdAsync(itemId, cancellationToken); - if (item == null) - { - throw new BusinessException(ErrorCodes.NotFound, "字典项不存在"); - } - - return item; - } - - private long ResolveTargetTenant(DictionaryScope scope) - { - var tenantId = tenantProvider.GetCurrentTenantId(); - if (scope == DictionaryScope.System) - { - EnsureSystemTenant(tenantId); - return 0; - } - - if (tenantId == 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "业务参数需指定租户"); - } - - return tenantId; - } - - private static string NormalizeCode(string code) => code.Trim().ToLowerInvariant(); - - private static DictionaryScope ResolveScopeForQuery(DictionaryScope? requestedScope, long tenantId) - { - if (requestedScope.HasValue) - { - return requestedScope.Value; - } - - return tenantId == 0 ? DictionaryScope.System : DictionaryScope.Business; - } - - private void EnsureScopePermission(DictionaryScope scope) - { - var tenantId = tenantProvider.GetCurrentTenantId(); - - // 1. (空行后) 租户端不允许操作系统字典 - if (scope == DictionaryScope.System && tenantId != 0) - { - throw new BusinessException(ErrorCodes.Forbidden, "租户端不允许操作系统字典"); - } - } - - private void EnsureSystemTenant(long tenantId) - { - // 1. (空行后) 系统字典只能在系统租户(TenantId=0)上下文中操作 - if (tenantId != 0) - { - throw new BusinessException(ErrorCodes.Forbidden, "租户端不允许操作系统字典"); - } - } - - private async Task InvalidateCacheAsync(DictionaryGroup group, CancellationToken cancellationToken) - { - await cache.RemoveAsync(group.TenantId, group.Code, cancellationToken); - if (group.Scope == DictionaryScope.Business) - { - return; - } - - // 系统参数更新需要逐租户重新合并,由调用方在下一次请求时重新加载 - } - - private async Task> GetOrLoadCacheAsync(long tenantId, string code, CancellationToken cancellationToken) - { - // 1. 先查缓存 - var cached = await cache.GetAsync(tenantId, code, cancellationToken); - if (cached != null) - { - return cached; - } - - // 2. 从仓储加载并写入缓存 - var entities = await repository.GetItemsByCodesAsync(new[] { code }, tenantId, includeSystem: false, cancellationToken); - var items = entities - .Where(item => item.IsEnabled && (item.Group?.IsEnabled ?? true)) - .Select(MapItem) - .OrderBy(item => item.SortOrder) - .ToList(); - - await cache.SetAsync(tenantId, code, items, cancellationToken); - return items; - } - - private static IReadOnlyList MergeItems(IReadOnlyList systemItems, IReadOnlyList tenantItems) - { - if (tenantItems.Count == 0) - { - return systemItems; - } - - if (systemItems.Count == 0) - { - return tenantItems; - } - - return systemItems.Concat(tenantItems) - .OrderBy(item => item.SortOrder) - .ToList(); - } - - private static DictionaryGroupDto MapGroup(DictionaryGroup group, bool includeItems, IReadOnlyList? items = null) - { - return new DictionaryGroupDto - { - Id = group.Id, - Code = group.Code, - TenantId = group.TenantId, - Name = group.Name, - Scope = group.Scope, - Description = group.Description, - AllowOverride = group.AllowOverride, - IsEnabled = group.IsEnabled, - CreatedAt = group.CreatedAt, - UpdatedAt = group.UpdatedAt, - RowVersion = group.RowVersion, - Items = includeItems ? items ?? group.Items.Select(MapItem).ToList() : Array.Empty() - }; - } - - private static DictionaryItemDto MapItem(DictionaryItem item) - => new() - { - Id = item.Id, - GroupId = item.GroupId, - Key = item.Key, - Value = DictionaryValueConverter.Deserialize(item.Value), - IsDefault = item.IsDefault, - IsEnabled = item.IsEnabled, - SortOrder = item.SortOrder, - Description = item.Description, - Source = item.TenantId == 0 ? "system" : "tenant", - RowVersion = item.RowVersion - }; - - private static bool IsConcurrencyException(Exception exception) - => string.Equals(exception.GetType().Name, "DbUpdateConcurrencyException", StringComparison.Ordinal); -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryCacheKeys.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryCacheKeys.cs deleted file mode 100644 index 9a45af5..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryCacheKeys.cs +++ /dev/null @@ -1,44 +0,0 @@ -using TakeoutSaaS.Domain.Dictionary.Enums; -using TakeoutSaaS.Domain.Dictionary.ValueObjects; - -namespace TakeoutSaaS.Application.Dictionary.Services; - -/// -/// 字典缓存键生成器。 -/// -internal static class DictionaryCacheKeys -{ - internal const string DictionaryPrefix = "dict:"; - internal const string GroupPrefix = "dict:groups:"; - internal const string ItemPrefix = "dict:items:"; - - internal static string BuildDictionaryKey(long tenantId, DictionaryCode code) - => $"{DictionaryPrefix}{tenantId}:{code.Value}"; - - internal static string BuildGroupKey( - long tenantId, - DictionaryScope scope, - int page, - int pageSize, - string? keyword, - bool? isEnabled, - string? sortBy, - bool sortDescending) - { - return $"{GroupPrefix}{tenantId}:{scope}:{page}:{pageSize}:{Normalize(keyword)}:{Normalize(isEnabled)}:{Normalize(sortBy)}:{(sortDescending ? "desc" : "asc")}"; - } - - internal static string BuildGroupPrefix(long tenantId) - => $"{GroupPrefix}{tenantId}:"; - - internal static string BuildItemKey(long groupId) - => $"{ItemPrefix}{groupId}"; - - private static string Normalize(string? value) - => string.IsNullOrWhiteSpace(value) - ? "all" - : value.Trim().ToLowerInvariant().Replace(":", "_", StringComparison.Ordinal); - - private static string Normalize(bool? value) - => value.HasValue ? (value.Value ? "1" : "0") : "all"; -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryCommandService.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryCommandService.cs deleted file mode 100644 index c34a8db..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryCommandService.cs +++ /dev/null @@ -1,343 +0,0 @@ -using System.Security.Cryptography; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.Dictionary.Abstractions; -using TakeoutSaaS.Application.Dictionary.Contracts; -using TakeoutSaaS.Application.Dictionary.Models; -using TakeoutSaaS.Domain.Dictionary.Entities; -using TakeoutSaaS.Domain.Dictionary.Enums; -using TakeoutSaaS.Domain.Dictionary.Repositories; -using TakeoutSaaS.Domain.Dictionary.ValueObjects; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Dictionary.Services; - -/// -/// 字典写操作服务。 -/// -public sealed class DictionaryCommandService( - IDictionaryGroupRepository groupRepository, - IDictionaryItemRepository itemRepository, - IDictionaryHybridCache cache, - ITenantProvider tenantProvider, - ILogger logger) -{ - /// - /// 创建字典分组。 - /// - public async Task CreateGroupAsync(CreateDictionaryGroupRequest request, CancellationToken cancellationToken = default) - { - var targetTenantId = ResolveTargetTenant(request.Scope); - var code = new DictionaryCode(request.Code); - - var existing = await groupRepository.GetByCodeAsync(targetTenantId, code, cancellationToken); - if (existing != null) - { - throw new BusinessException(ErrorCodes.Conflict, $"字典分组编码 {code.Value} 已存在"); - } - - var group = new DictionaryGroup - { - TenantId = targetTenantId, - Code = code, - Name = request.Name.Trim(), - Scope = request.Scope, - AllowOverride = request.AllowOverride, - Description = request.Description?.Trim(), - IsEnabled = true, - RowVersion = RandomNumberGenerator.GetBytes(16) - }; - - await groupRepository.AddAsync(group, cancellationToken); - await groupRepository.SaveChangesAsync(cancellationToken); - await cache.InvalidateAsync( - DictionaryCacheKeys.BuildGroupPrefix(targetTenantId), - CacheInvalidationOperation.Create, - cancellationToken); - - logger.LogInformation("创建字典分组 {GroupCode}", group.Code); - return DictionaryMapper.ToGroupDto(group); - } - - /// - /// 更新字典分组。 - /// - public async Task UpdateGroupAsync(long groupId, UpdateDictionaryGroupRequest request, CancellationToken cancellationToken = default) - { - var group = await RequireGroupAsync(groupId, cancellationToken); - EnsureGroupAccess(group); - - EnsureRowVersion(request.RowVersion, group.RowVersion, "字典分组"); - - group.Name = request.Name.Trim(); - group.Description = request.Description?.Trim(); - group.IsEnabled = request.IsEnabled; - group.AllowOverride = request.AllowOverride; - group.RowVersion = RandomNumberGenerator.GetBytes(16); - - try - { - await groupRepository.SaveChangesAsync(cancellationToken); - } - catch (Exception exception) when (IsConcurrencyException(exception)) - { - throw new BusinessException(ErrorCodes.Conflict, "字典分组已被修改,请刷新后重试"); - } - - await InvalidateGroupCacheAsync(group, CacheInvalidationOperation.Update, cancellationToken); - logger.LogInformation("更新字典分组 {GroupId}", group.Id); - return DictionaryMapper.ToGroupDto(group); - } - - /// - /// 删除字典分组。 - /// - public async Task DeleteGroupAsync(long groupId, CancellationToken cancellationToken = default) - { - var group = await groupRepository.GetByIdAsync(groupId, cancellationToken); - if (group == null) - { - return false; - } - - EnsureGroupAccess(group); - - var items = await itemRepository.GetByGroupIdAsync(group.TenantId, group.Id, cancellationToken); - foreach (var item in items) - { - await itemRepository.RemoveAsync(item, cancellationToken); - } - - await groupRepository.RemoveAsync(group, cancellationToken); - await groupRepository.SaveChangesAsync(cancellationToken); - await InvalidateGroupCacheAsync(group, CacheInvalidationOperation.Delete, cancellationToken); - - logger.LogInformation("删除字典分组 {GroupId}", group.Id); - return true; - } - - /// - /// 创建字典项。 - /// - public async Task CreateItemAsync(CreateDictionaryItemRequest request, CancellationToken cancellationToken = default) - { - var group = await RequireGroupAsync(request.GroupId, cancellationToken); - EnsureGroupAccess(group); - - var items = await itemRepository.GetByGroupIdAsync(group.TenantId, group.Id, cancellationToken); - var normalizedKey = request.Key.Trim(); - if (items.Any(item => string.Equals(item.Key, normalizedKey, StringComparison.OrdinalIgnoreCase))) - { - throw new BusinessException(ErrorCodes.Conflict, $"字典项键 {normalizedKey} 已存在"); - } - - var sortOrder = request.SortOrder; - if (sortOrder <= 0) - { - sortOrder = items.Count == 0 ? 10 : items.Max(item => item.SortOrder) + 10; - } - - var item = new DictionaryItem - { - TenantId = group.TenantId, - GroupId = group.Id, - Key = normalizedKey, - Value = DictionaryValueConverter.Serialize(request.Value), - Description = request.Description?.Trim(), - SortOrder = sortOrder, - IsDefault = request.IsDefault, - IsEnabled = request.IsEnabled, - RowVersion = RandomNumberGenerator.GetBytes(16) - }; - - await itemRepository.AddAsync(item, cancellationToken); - await groupRepository.SaveChangesAsync(cancellationToken); - await InvalidateItemCacheAsync(group, CacheInvalidationOperation.Create, cancellationToken); - - logger.LogInformation("新增字典项 {ItemId}", item.Id); - return DictionaryMapper.ToItemDto(item); - } - - /// - /// 更新字典项。 - /// - public async Task UpdateItemAsync(long itemId, UpdateDictionaryItemRequest request, CancellationToken cancellationToken = default) - { - var item = await RequireItemAsync(itemId, cancellationToken); - var group = await RequireGroupAsync(item.GroupId, cancellationToken); - EnsureGroupAccess(group); - - EnsureRowVersion(request.RowVersion, item.RowVersion, "字典项"); - - var normalizedKey = request.Key.Trim(); - if (!string.Equals(item.Key, normalizedKey, StringComparison.OrdinalIgnoreCase)) - { - var items = await itemRepository.GetByGroupIdAsync(group.TenantId, group.Id, cancellationToken); - if (items.Any(existing => existing.Id != item.Id && string.Equals(existing.Key, normalizedKey, StringComparison.OrdinalIgnoreCase))) - { - throw new BusinessException(ErrorCodes.Conflict, $"字典项键 {normalizedKey} 已存在"); - } - } - - item.Key = normalizedKey; - item.Value = DictionaryValueConverter.Serialize(request.Value); - item.Description = request.Description?.Trim(); - item.SortOrder = request.SortOrder; - item.IsDefault = request.IsDefault; - item.IsEnabled = request.IsEnabled; - item.RowVersion = RandomNumberGenerator.GetBytes(16); - - try - { - await groupRepository.SaveChangesAsync(cancellationToken); - } - catch (Exception exception) when (IsConcurrencyException(exception)) - { - throw new BusinessException(ErrorCodes.Conflict, "字典项已被修改,请刷新后重试"); - } - - await InvalidateItemCacheAsync(group, CacheInvalidationOperation.Update, cancellationToken); - logger.LogInformation("更新字典项 {ItemId}", item.Id); - return DictionaryMapper.ToItemDto(item); - } - - /// - /// 删除字典项。 - /// - public async Task DeleteItemAsync(long itemId, CancellationToken cancellationToken = default) - { - var item = await itemRepository.GetByIdAsync(itemId, cancellationToken); - if (item == null) - { - return false; - } - - var group = await RequireGroupAsync(item.GroupId, cancellationToken); - EnsureGroupAccess(group); - - await itemRepository.RemoveAsync(item, cancellationToken); - await groupRepository.SaveChangesAsync(cancellationToken); - await InvalidateItemCacheAsync(group, CacheInvalidationOperation.Delete, cancellationToken); - - logger.LogInformation("删除字典项 {ItemId}", item.Id); - return true; - } - - private long ResolveTargetTenant(DictionaryScope scope) - { - var tenantId = tenantProvider.GetCurrentTenantId(); - if (scope == DictionaryScope.System) - { - // 1. (空行后) 租户端禁止写入系统字典 - if (tenantId != 0) - { - throw new BusinessException(ErrorCodes.Forbidden, "租户端不允许创建系统字典"); - } - - return 0; - } - - // 2. (空行后) 业务字典必须在租户上下文中创建 - if (tenantId == 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "业务字典必须在租户上下文中创建"); - } - - return tenantId; - } - - private void EnsureGroupAccess(DictionaryGroup group) - { - var tenantId = tenantProvider.GetCurrentTenantId(); - - // 1. (空行后) 租户端不允许操作系统字典 - if (group.Scope == DictionaryScope.System && tenantId != 0) - { - throw new BusinessException(ErrorCodes.Forbidden, "租户端不允许操作系统字典"); - } - - // 2. (空行后) 业务字典必须属于当前租户 - if (group.Scope == DictionaryScope.Business && tenantId != group.TenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "无权操作其他租户字典"); - } - } - - private static void EnsureRowVersion(byte[]? requestVersion, byte[] entityVersion, string resourceName) - { - if (requestVersion == null || requestVersion.Length == 0) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "RowVersion 不能为空"); - } - - if (!requestVersion.SequenceEqual(entityVersion)) - { - throw new BusinessException(ErrorCodes.Conflict, $"{resourceName}已被修改,请刷新后重试"); - } - } - - private async Task RequireGroupAsync(long groupId, CancellationToken cancellationToken) - { - var group = await groupRepository.GetByIdAsync(groupId, cancellationToken); - if (group == null) - { - throw new BusinessException(ErrorCodes.NotFound, "字典分组不存在"); - } - - return group; - } - - private async Task RequireItemAsync(long itemId, CancellationToken cancellationToken) - { - var item = await itemRepository.GetByIdAsync(itemId, cancellationToken); - if (item == null) - { - throw new BusinessException(ErrorCodes.NotFound, "字典项不存在"); - } - - return item; - } - - private Task InvalidateGroupCacheAsync( - DictionaryGroup group, - CacheInvalidationOperation operation, - CancellationToken cancellationToken) - { - var tasks = new List - { - cache.InvalidateAsync(DictionaryCacheKeys.BuildGroupPrefix(group.TenantId), operation, cancellationToken), - cache.InvalidateAsync(DictionaryCacheKeys.BuildItemKey(group.Id), operation, cancellationToken), - cache.InvalidateAsync(DictionaryCacheKeys.BuildDictionaryKey(group.TenantId, group.Code), operation, cancellationToken) - }; - - if (group.Scope == DictionaryScope.System) - { - tasks.Add(cache.InvalidateAsync(DictionaryCacheKeys.DictionaryPrefix, operation, cancellationToken)); - } - - return Task.WhenAll(tasks); - } - - private Task InvalidateItemCacheAsync( - DictionaryGroup group, - CacheInvalidationOperation operation, - CancellationToken cancellationToken) - { - var tasks = new List - { - cache.InvalidateAsync(DictionaryCacheKeys.BuildItemKey(group.Id), operation, cancellationToken), - cache.InvalidateAsync(DictionaryCacheKeys.BuildDictionaryKey(group.TenantId, group.Code), operation, cancellationToken) - }; - - if (group.Scope == DictionaryScope.System) - { - tasks.Add(cache.InvalidateAsync(DictionaryCacheKeys.DictionaryPrefix, operation, cancellationToken)); - } - - return Task.WhenAll(tasks); - } - - private static bool IsConcurrencyException(Exception exception) - => string.Equals(exception.GetType().Name, "DbUpdateConcurrencyException", StringComparison.Ordinal); -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryImportExportService.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryImportExportService.cs deleted file mode 100644 index 9e085a7..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryImportExportService.cs +++ /dev/null @@ -1,483 +0,0 @@ -using System.Diagnostics; -using System.Security.Cryptography; -using System.Text; -using System.Text.Json; -using TakeoutSaaS.Application.Dictionary.Abstractions; -using TakeoutSaaS.Application.Dictionary.Contracts; -using TakeoutSaaS.Application.Dictionary.Models; -using TakeoutSaaS.Domain.Dictionary.Entities; -using TakeoutSaaS.Domain.Dictionary.Enums; -using TakeoutSaaS.Domain.Dictionary.Repositories; -using TakeoutSaaS.Domain.Dictionary.ValueObjects; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; -using Microsoft.Extensions.Logging; - -namespace TakeoutSaaS.Application.Dictionary.Services; - -/// -/// 字典导入导出服务。 -/// -public sealed class DictionaryImportExportService( - ICsvDictionaryParser csvParser, - IJsonDictionaryParser jsonParser, - IDictionaryGroupRepository groupRepository, - IDictionaryItemRepository itemRepository, - IDictionaryImportLogRepository importLogRepository, - IDictionaryHybridCache cache, - ITenantProvider tenantProvider, - ICurrentUserAccessor currentUser, - ILogger logger) -{ - private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web); - - /// - /// 导出 CSV。 - /// - public async Task ExportToCsvAsync(long groupId, Stream output, CancellationToken cancellationToken = default) - { - var group = await RequireGroupAsync(groupId, cancellationToken); - EnsureGroupReadable(group); - - var items = await ResolveExportItemsAsync(group, cancellationToken); - await WriteCsvAsync(group, items, output, cancellationToken); - } - - /// - /// 导出 JSON。 - /// - public async Task ExportToJsonAsync(long groupId, Stream output, CancellationToken cancellationToken = default) - { - var group = await RequireGroupAsync(groupId, cancellationToken); - EnsureGroupReadable(group); - - var items = await ResolveExportItemsAsync(group, cancellationToken); - var payload = items.Select(item => new DictionaryExportRow - { - Code = group.Code.Value, - Key = item.Key, - Value = item.Value, - SortOrder = item.SortOrder, - IsEnabled = item.IsEnabled, - Description = item.Description, - Source = item.Source - }); - - await JsonSerializer.SerializeAsync(output, payload, JsonOptions, cancellationToken); - } - - /// - /// 导入 CSV。 - /// - public async Task ImportFromCsvAsync(DictionaryImportRequest request, CancellationToken cancellationToken = default) - { - var rows = await csvParser.ParseAsync(request.FileStream, cancellationToken); - return await ImportAsync(request, rows, "CSV", cancellationToken); - } - - /// - /// 导入 JSON。 - /// - public async Task ImportFromJsonAsync(DictionaryImportRequest request, CancellationToken cancellationToken = default) - { - var rows = await jsonParser.ParseAsync(request.FileStream, cancellationToken); - return await ImportAsync(request, rows, "JSON", cancellationToken); - } - - private async Task ImportAsync( - DictionaryImportRequest request, - IReadOnlyList rows, - string format, - CancellationToken cancellationToken) - { - var stopwatch = Stopwatch.StartNew(); - var group = await RequireGroupAsync(request.GroupId, cancellationToken); - EnsureGroupWritable(group); - - var errors = new List(); - var validRows = new List(rows.Count); - var hasFatalErrors = false; - - foreach (var row in rows) - { - if (!TryNormalizeRow(group, row, errors, out var normalized)) - { - hasFatalErrors = true; - continue; - } - - validRows.Add(normalized); - } - - if (hasFatalErrors) - { - var failed = BuildResult(0, 0, errors, stopwatch.Elapsed); - await RecordImportLogAsync(request, group, format, failed, stopwatch.Elapsed, cancellationToken); - return failed; - } - - var existingItems = await itemRepository.GetByGroupIdAsync(group.TenantId, group.Id, cancellationToken); - var existingMap = existingItems.ToDictionary(item => item.Key, StringComparer.OrdinalIgnoreCase); - var seenKeys = new HashSet(StringComparer.OrdinalIgnoreCase); - - var successCount = 0; - var skipCount = 0; - var nextSortOrder = existingItems.Count == 0 ? 0 : existingItems.Max(item => item.SortOrder); - - foreach (var row in validRows) - { - cancellationToken.ThrowIfCancellationRequested(); - - if (!seenKeys.Add(row.Key)) - { - skipCount++; - errors.Add(CreateError(row.RowNumber, "key", $"字典项键 {row.Key} 在导入文件中重复")); - continue; - } - - if (existingMap.TryGetValue(row.Key, out var existing)) - { - if (request.ConflictMode != ConflictResolutionMode.Overwrite) - { - skipCount++; - errors.Add(CreateError(row.RowNumber, "key", $"字典项键 {row.Key} 已存在")); - continue; - } - - ApplyUpdate(existing, row, existing.SortOrder, overwriteSort: row.SortOrder.HasValue); - await itemRepository.UpdateAsync(existing, cancellationToken); - successCount++; - continue; - } - - var sortOrder = row.SortOrder ?? 0; - if (!row.SortOrder.HasValue) - { - nextSortOrder = nextSortOrder == 0 ? 10 : nextSortOrder + 10; - sortOrder = nextSortOrder; - } - - var item = new DictionaryItem - { - TenantId = group.TenantId, - GroupId = group.Id, - Key = row.Key, - Value = row.ValueJson, - SortOrder = sortOrder, - IsEnabled = row.IsEnabled ?? true, - IsDefault = false, - Description = row.Description, - RowVersion = RandomNumberGenerator.GetBytes(16) - }; - - await itemRepository.AddAsync(item, cancellationToken); - existingMap[item.Key] = item; - successCount++; - } - - await itemRepository.SaveChangesAsync(cancellationToken); - await InvalidateGroupCacheAsync(group, cancellationToken); - - var result = BuildResult(successCount, skipCount, errors, stopwatch.Elapsed); - await RecordImportLogAsync(request, group, format, result, stopwatch.Elapsed, cancellationToken); - return result; - } - - private static void ApplyUpdate(DictionaryItem item, NormalizedRow row, int defaultSortOrder, bool overwriteSort) - { - item.Key = row.Key; - item.Value = row.ValueJson; - if (overwriteSort) - { - item.SortOrder = row.SortOrder ?? defaultSortOrder; - } - - if (row.IsEnabled.HasValue) - { - item.IsEnabled = row.IsEnabled.Value; - } - - if (!string.IsNullOrWhiteSpace(row.Description)) - { - item.Description = row.Description; - } - - } - - private async Task> ResolveExportItemsAsync(DictionaryGroup group, CancellationToken cancellationToken) - { - var tenantId = tenantProvider.GetCurrentTenantId(); - - if (group.Scope == DictionaryScope.System && tenantId != 0) - { - var mergedItems = await itemRepository.GetMergedItemsAsync(tenantId, group.Id, includeOverrides: true, cancellationToken); - return mergedItems.Select(DictionaryMapper.ToItemDto).ToList(); - } - - var items = await itemRepository.GetByGroupIdAsync(group.TenantId, group.Id, cancellationToken); - return items.Select(DictionaryMapper.ToItemDto).ToList(); - } - - private static async Task WriteCsvAsync( - DictionaryGroup group, - IReadOnlyList items, - Stream output, - CancellationToken cancellationToken) - { - await using var writer = new StreamWriter(output, new UTF8Encoding(encoderShouldEmitUTF8Identifier: true), leaveOpen: true); - - await writer.WriteLineAsync("code,key,value,sortOrder,isEnabled,description,source"); - foreach (var item in items) - { - cancellationToken.ThrowIfCancellationRequested(); - - var valueJson = JsonSerializer.Serialize(item.Value, JsonOptions); - var row = new[] - { - group.Code.Value, - item.Key, - valueJson, - item.SortOrder.ToString(), - item.IsEnabled ? "true" : "false", - item.Description ?? string.Empty, - item.Source - }; - - await writer.WriteLineAsync(ToCsvRow(row)); - } - - await writer.FlushAsync(cancellationToken); - } - - private static string ToCsvRow(IEnumerable fields) - => string.Join(",", fields.Select(EscapeCsvField)); - - private static string EscapeCsvField(string value) - { - if (value.Contains('"', StringComparison.Ordinal)) - { - value = value.Replace("\"", "\"\""); - } - - if (value.Contains(',', StringComparison.Ordinal) || - value.Contains('\n', StringComparison.Ordinal) || - value.Contains('\r', StringComparison.Ordinal) || - value.Contains('"', StringComparison.Ordinal)) - { - return $"\"{value}\""; - } - - return value; - } - - private bool TryNormalizeRow( - DictionaryGroup group, - DictionaryImportRow row, - ICollection errors, - out NormalizedRow normalized) - { - normalized = default; - - if (!string.IsNullOrWhiteSpace(row.Code) && - !string.Equals(row.Code.Trim(), group.Code.Value, StringComparison.OrdinalIgnoreCase)) - { - errors.Add(CreateError(row.RowNumber, "code", "字典分组编码不匹配")); - return false; - } - - if (string.IsNullOrWhiteSpace(row.Key)) - { - errors.Add(CreateError(row.RowNumber, "key", "字典项键不能为空")); - return false; - } - - var key = row.Key.Trim(); - if (key.Length > 128) - { - errors.Add(CreateError(row.RowNumber, "key", "字典项键长度不能超过 128")); - return false; - } - - if (string.IsNullOrWhiteSpace(row.Value)) - { - errors.Add(CreateError(row.RowNumber, "value", "字典项值不能为空")); - return false; - } - - string valueJson; - try - { - var i18n = I18nValue.FromJson(row.Value); - valueJson = i18n.ToJson(); - } - catch (ArgumentException) - { - errors.Add(CreateError(row.RowNumber, "value", "字典项值必须为合法的多语言 JSON")); - return false; - } - catch (JsonException) - { - errors.Add(CreateError(row.RowNumber, "value", "字典项值必须为合法的多语言 JSON")); - return false; - } - - if (row.SortOrder.HasValue && row.SortOrder.Value < 0) - { - errors.Add(CreateError(row.RowNumber, "sortOrder", "排序值不能小于 0")); - return false; - } - - normalized = new NormalizedRow - { - RowNumber = row.RowNumber, - Key = key, - ValueJson = valueJson, - SortOrder = row.SortOrder, - IsEnabled = row.IsEnabled, - Description = row.Description?.Trim() - }; - - return true; - } - - private static DictionaryImportResultDto BuildResult( - int successCount, - int skipCount, - IReadOnlyList errors, - TimeSpan duration) - { - return new DictionaryImportResultDto - { - SuccessCount = successCount, - SkipCount = skipCount, - ErrorCount = errors.Count, - Errors = errors.ToArray(), - Duration = duration - }; - } - - private async Task RecordImportLogAsync( - DictionaryImportRequest request, - DictionaryGroup group, - string format, - DictionaryImportResultDto result, - TimeSpan duration, - CancellationToken cancellationToken) - { - try - { - var log = new DictionaryImportLog - { - TenantId = group.TenantId, - OperatorId = currentUser.UserId, - DictionaryGroupCode = group.Code.Value, - FileName = request.FileName, - FileSize = request.FileSize, - Format = format, - ConflictMode = request.ConflictMode, - SuccessCount = result.SuccessCount, - SkipCount = result.SkipCount, - ErrorDetails = result.Errors.Count == 0 ? null : JsonSerializer.Serialize(result.Errors, JsonOptions), - ProcessedAt = DateTime.UtcNow, - Duration = duration - }; - - await importLogRepository.AddAsync(log, cancellationToken); - await importLogRepository.SaveChangesAsync(cancellationToken); - } - catch (Exception exception) - { - logger.LogWarning(exception, "记录字典导入日志失败"); - } - } - - private async Task InvalidateGroupCacheAsync(DictionaryGroup group, CancellationToken cancellationToken) - { - var tasks = new List - { - cache.InvalidateAsync(DictionaryCacheKeys.BuildGroupPrefix(group.TenantId), CacheInvalidationOperation.Update, cancellationToken), - cache.InvalidateAsync(DictionaryCacheKeys.BuildItemKey(group.Id), CacheInvalidationOperation.Update, cancellationToken), - cache.InvalidateAsync(DictionaryCacheKeys.BuildDictionaryKey(group.TenantId, group.Code), CacheInvalidationOperation.Update, cancellationToken) - }; - - if (group.Scope == DictionaryScope.System) - { - tasks.Add(cache.InvalidateAsync(DictionaryCacheKeys.DictionaryPrefix, CacheInvalidationOperation.Update, cancellationToken)); - } - - await Task.WhenAll(tasks); - } - - private async Task RequireGroupAsync(long groupId, CancellationToken cancellationToken) - { - var group = await groupRepository.GetByIdAsync(groupId, cancellationToken); - if (group == null) - { - throw new BusinessException(ErrorCodes.NotFound, "字典分组不存在"); - } - - return group; - } - - private void EnsureGroupAccess(DictionaryGroup group) - { - var tenantId = tenantProvider.GetCurrentTenantId(); - - // 1. (空行后) 租户端不允许操作系统字典 - if (group.Scope == DictionaryScope.System && tenantId != 0) - { - throw new BusinessException(ErrorCodes.Forbidden, "租户端不允许操作系统字典"); - } - - // 2. (空行后) 业务字典必须属于当前租户 - if (group.Scope == DictionaryScope.Business && tenantId != group.TenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "无权操作其他租户字典"); - } - } - - private void EnsureGroupReadable(DictionaryGroup group) - { - var tenantId = tenantProvider.GetCurrentTenantId(); - if (tenantId != 0 && group.Scope == DictionaryScope.Business && group.TenantId != tenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "无权访问其他租户字典"); - } - } - - private void EnsureGroupWritable(DictionaryGroup group) - { - EnsureGroupAccess(group); - } - - private static DictionaryImportResultDto.ImportError CreateError(int rowNumber, string field, string message) - => new() - { - RowNumber = rowNumber, - Field = field, - Message = message - }; - - private sealed class DictionaryExportRow - { - public string Code { get; init; } = string.Empty; - public string Key { get; init; } = string.Empty; - public Dictionary Value { get; init; } = new(StringComparer.OrdinalIgnoreCase); - public int SortOrder { get; init; } - public bool IsEnabled { get; init; } - public string? Description { get; init; } - public string Source { get; init; } = "system"; - } - - private readonly struct NormalizedRow - { - public int RowNumber { get; init; } - public string Key { get; init; } - public string ValueJson { get; init; } - public int? SortOrder { get; init; } - public bool? IsEnabled { get; init; } - public string? Description { get; init; } - } -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryLabelOverrideService.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryLabelOverrideService.cs deleted file mode 100644 index 8d3346c..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryLabelOverrideService.cs +++ /dev/null @@ -1,180 +0,0 @@ -using TakeoutSaaS.Application.Dictionary.Models; -using TakeoutSaaS.Domain.Dictionary.Entities; -using TakeoutSaaS.Domain.Dictionary.Enums; -using TakeoutSaaS.Domain.Dictionary.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; - -namespace TakeoutSaaS.Application.Dictionary.Services; - -/// -/// 字典标签覆盖服务。 -/// -public sealed class DictionaryLabelOverrideService( - IDictionaryLabelOverrideRepository overrideRepository, - IDictionaryItemRepository itemRepository) -{ - /// - /// 获取租户的所有标签覆盖。 - /// - /// 租户 ID。 - /// 可选的覆盖类型过滤。 - /// 取消标记。 - public async Task> GetOverridesAsync( - long tenantId, - OverrideType? overrideType = null, - CancellationToken cancellationToken = default) - { - var overrides = await overrideRepository.ListByTenantAsync(tenantId, overrideType, cancellationToken); - return overrides.Select(MapToDto).ToList(); - } - - /// - /// 获取指定字典项的覆盖配置。 - /// - /// 租户 ID。 - /// 字典项 ID。 - /// 取消标记。 - public async Task GetOverrideByItemIdAsync( - long tenantId, - long dictionaryItemId, - CancellationToken cancellationToken = default) - { - var entity = await overrideRepository.GetByItemIdAsync(tenantId, dictionaryItemId, cancellationToken); - return entity == null ? null : MapToDto(entity); - } - - /// - /// 创建或更新租户对系统字典的标签覆盖(租户定制)。 - /// - /// 租户 ID。 - /// 覆盖请求。 - /// 操作人 ID。 - /// 取消标记。 - public async Task UpsertTenantOverrideAsync( - long tenantId, - UpsertLabelOverrideRequest request, - long operatorId, - CancellationToken cancellationToken = default) - { - // 1. 验证字典项存在且为系统字典 - var item = await itemRepository.GetByIdAsync(request.DictionaryItemId, cancellationToken); - if (item == null) - { - throw new BusinessException(ErrorCodes.NotFound, "字典项不存在"); - } - - if (item.TenantId != 0) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "租户只能覆盖系统字典项"); - } - - // 2. 查找现有覆盖或创建新记录 - var existing = await overrideRepository.GetByItemIdAsync(tenantId, request.DictionaryItemId, cancellationToken); - var now = DateTime.UtcNow; - // 2.1 更新现有覆盖或创建新记录 - if (existing != null) - { - // 2.2 仅允许租户定制类型被租户修改,其他类型视为系统保留数据 - if (existing.OverrideType != OverrideType.TenantCustomization) - { - throw new BusinessException(ErrorCodes.Forbidden, "该覆盖记录不允许由租户修改"); - } - - existing.OverrideValue = DictionaryValueConverter.Serialize(request.OverrideValue); - existing.Reason = request.Reason; - existing.UpdatedAt = now; - existing.UpdatedBy = operatorId; - await overrideRepository.UpdateAsync(existing, cancellationToken); - } - else - { - existing = new DictionaryLabelOverride - { - TenantId = tenantId, - DictionaryItemId = request.DictionaryItemId, - OriginalValue = item.Value, - OverrideValue = DictionaryValueConverter.Serialize(request.OverrideValue), - OverrideType = OverrideType.TenantCustomization, - Reason = request.Reason, - CreatedAt = now, - CreatedBy = operatorId - }; - await overrideRepository.AddAsync(existing, cancellationToken); - } - - await overrideRepository.SaveChangesAsync(cancellationToken); - - // 重新加载以获取完整信息 - existing.DictionaryItem = item; - return MapToDto(existing); - } - - /// - /// 删除覆盖配置。 - /// - /// 租户 ID。 - /// 字典项 ID。 - /// 操作人 ID。 - /// 取消标记。 - public async Task DeleteOverrideAsync( - long tenantId, - long dictionaryItemId, - long operatorId, - CancellationToken cancellationToken = default) - { - var existing = await overrideRepository.GetByItemIdAsync(tenantId, dictionaryItemId, cancellationToken); - if (existing == null) - { - return false; - } - - // 1. (空行后) 仅允许删除租户定制类型,其他类型视为系统保留数据 - if (existing.OverrideType != OverrideType.TenantCustomization) - { - throw new BusinessException(ErrorCodes.Forbidden, "该覆盖记录不允许由租户删除"); - } - - existing.DeletedBy = operatorId; - await overrideRepository.DeleteAsync(existing, cancellationToken); - await overrideRepository.SaveChangesAsync(cancellationToken); - return true; - } - - /// - /// 批量获取字典项的覆盖值映射。 - /// - /// 租户 ID。 - /// 字典项 ID 列表。 - /// 取消标记。 - /// 字典项 ID 到覆盖值的映射。 - public async Task>> GetOverrideValuesMapAsync( - long tenantId, - IEnumerable dictionaryItemIds, - CancellationToken cancellationToken = default) - { - var overrides = await overrideRepository.GetByItemIdsAsync(tenantId, dictionaryItemIds, cancellationToken); - return overrides.ToDictionary( - x => x.DictionaryItemId, - x => DictionaryValueConverter.Deserialize(x.OverrideValue)); - } - - private static LabelOverrideDto MapToDto(DictionaryLabelOverride entity) - { - return new LabelOverrideDto - { - Id = entity.Id, - TenantId = entity.TenantId, - DictionaryItemId = entity.DictionaryItemId, - DictionaryItemKey = entity.DictionaryItem?.Key ?? string.Empty, - OriginalValue = DictionaryValueConverter.Deserialize(entity.OriginalValue), - OverrideValue = DictionaryValueConverter.Deserialize(entity.OverrideValue), - OverrideType = entity.OverrideType, - Reason = entity.Reason, - CreatedAt = entity.CreatedAt, - UpdatedAt = entity.UpdatedAt, - CreatedBy = entity.CreatedBy, - UpdatedBy = entity.UpdatedBy - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryMapper.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryMapper.cs deleted file mode 100644 index 06ea7fc..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryMapper.cs +++ /dev/null @@ -1,46 +0,0 @@ -using TakeoutSaaS.Application.Dictionary.Models; -using TakeoutSaaS.Domain.Dictionary.Entities; - -namespace TakeoutSaaS.Application.Dictionary.Services; - -/// -/// 字典实体映射辅助。 -/// -internal static class DictionaryMapper -{ - internal static DictionaryGroupDto ToGroupDto(DictionaryGroup group, IReadOnlyList? items = null) - { - return new DictionaryGroupDto - { - Id = group.Id, - TenantId = group.TenantId, - Code = group.Code, - Name = group.Name, - Scope = group.Scope, - AllowOverride = group.AllowOverride, - Description = group.Description, - IsEnabled = group.IsEnabled, - CreatedAt = group.CreatedAt, - UpdatedAt = group.UpdatedAt, - RowVersion = group.RowVersion, - Items = items ?? Array.Empty() - }; - } - - internal static DictionaryItemDto ToItemDto(DictionaryItem item) - { - return new DictionaryItemDto - { - Id = item.Id, - GroupId = item.GroupId, - Key = item.Key, - Value = DictionaryValueConverter.Deserialize(item.Value), - IsDefault = item.IsDefault, - IsEnabled = item.IsEnabled, - SortOrder = item.SortOrder, - Description = item.Description, - Source = item.TenantId == 0 ? "system" : "tenant", - RowVersion = item.RowVersion - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryMergeService.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryMergeService.cs deleted file mode 100644 index 61e4642..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryMergeService.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System.Text.Json; -using TakeoutSaaS.Application.Dictionary.Models; -using TakeoutSaaS.Domain.Dictionary.Entities; -using TakeoutSaaS.Domain.Dictionary.Enums; -using TakeoutSaaS.Domain.Dictionary.Repositories; - -namespace TakeoutSaaS.Application.Dictionary.Services; - -/// -/// 字典覆盖合并服务。 -/// -public sealed class DictionaryMergeService( - IDictionaryGroupRepository groupRepository, - IDictionaryItemRepository itemRepository, - ITenantDictionaryOverrideRepository overrideRepository) -{ - private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web); - - /// - /// 合并系统字典项与租户字典项。 - /// - public async Task> MergeItemsAsync( - long tenantId, - long systemGroupId, - CancellationToken cancellationToken = default) - { - var systemGroup = await groupRepository.GetByIdAsync(systemGroupId, cancellationToken); - if (systemGroup == null || systemGroup.Scope != DictionaryScope.System || !systemGroup.IsEnabled) - { - return Array.Empty(); - } - - var systemItems = await itemRepository.GetByGroupIdAsync(0, systemGroupId, cancellationToken); - var activeSystem = systemItems.Where(item => item.IsEnabled).ToList(); - - if (tenantId == 0) - { - return activeSystem.Select(DictionaryMapper.ToItemDto).ToList(); - } - - var overrideConfig = await overrideRepository.GetAsync(tenantId, systemGroupId, cancellationToken); - if (overrideConfig == null || !overrideConfig.OverrideEnabled) - { - return activeSystem.Select(DictionaryMapper.ToItemDto).ToList(); - } - - var tenantGroup = await groupRepository.GetByCodeAsync(tenantId, systemGroup.Code, cancellationToken); - var tenantItems = tenantGroup != null && tenantGroup.IsEnabled - ? await itemRepository.GetByGroupIdAsync(tenantId, tenantGroup.Id, cancellationToken) - : Array.Empty(); - - var activeTenant = tenantItems.Where(item => item.IsEnabled).ToList(); - var hiddenSet = new HashSet(overrideConfig.HiddenSystemItemIds); - var merged = activeSystem - .Where(item => !hiddenSet.Contains(item.Id)) - .Concat(activeTenant) - .Select(DictionaryMapper.ToItemDto) - .ToList(); - - var sortOrder = ParseSortOrder(overrideConfig.CustomSortOrder); - return merged - .OrderBy(item => sortOrder.TryGetValue(item.Id, out var custom) ? custom : item.SortOrder) - .ThenBy(item => item.SortOrder) - .ThenBy(item => item.Id) - .ToList(); - } - - private static Dictionary ParseSortOrder(string? json) - { - if (string.IsNullOrWhiteSpace(json)) - { - return new Dictionary(); - } - - try - { - return JsonSerializer.Deserialize>(json, JsonOptions) ?? new Dictionary(); - } - catch (JsonException) - { - return new Dictionary(); - } - } -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryOverrideService.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryOverrideService.cs deleted file mode 100644 index 325500a..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryOverrideService.cs +++ /dev/null @@ -1,322 +0,0 @@ -using System.Text.Json; -using TakeoutSaaS.Application.Dictionary.Abstractions; -using TakeoutSaaS.Application.Dictionary.Models; -using TakeoutSaaS.Domain.Dictionary.Entities; -using TakeoutSaaS.Domain.Dictionary.Enums; -using TakeoutSaaS.Domain.Dictionary.Repositories; -using TakeoutSaaS.Domain.Dictionary.ValueObjects; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; - -namespace TakeoutSaaS.Application.Dictionary.Services; - -/// -/// 租户字典覆盖配置服务。 -/// -public sealed class DictionaryOverrideService( - IDictionaryGroupRepository groupRepository, - IDictionaryItemRepository itemRepository, - ITenantDictionaryOverrideRepository overrideRepository, - IDictionaryHybridCache cache) -{ - private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web); - - /// - /// 获取租户覆盖配置列表。 - /// - public async Task> GetOverridesAsync(long tenantId, CancellationToken cancellationToken = default) - { - if (tenantId == 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "租户上下文缺失"); - } - - var configs = await overrideRepository.ListAsync(tenantId, cancellationToken); - if (configs.Count == 0) - { - return Array.Empty(); - } - - var groupIds = configs.Select(config => config.SystemDictionaryGroupId).Distinct().ToArray(); - var groups = await groupRepository.GetByIdsAsync(groupIds, cancellationToken); - var codeMap = groups - .Where(group => group.Scope == DictionaryScope.System) - .ToDictionary(group => group.Id, group => group.Code); - - var result = new List(configs.Count); - foreach (var config in configs) - { - if (codeMap.TryGetValue(config.SystemDictionaryGroupId, out var code)) - { - result.Add(MapOverrideDto(config, code)); - } - } - - return result; - } - - /// - /// 获取租户指定分组的覆盖配置。 - /// - public async Task GetOverrideAsync(long tenantId, string systemGroupCode, CancellationToken cancellationToken = default) - { - if (tenantId == 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "租户上下文缺失"); - } - - var systemGroup = await RequireSystemGroupAsync(systemGroupCode, cancellationToken); - var config = await overrideRepository.GetAsync(tenantId, systemGroup.Id, cancellationToken); - return config == null ? null : MapOverrideDto(config, systemGroup.Code); - } - - /// - /// 启用覆盖配置。 - /// - public async Task EnableOverrideAsync(long tenantId, string systemGroupCode, CancellationToken cancellationToken = default) - { - if (tenantId == 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "租户上下文缺失"); - } - - var systemGroup = await RequireSystemGroupAsync(systemGroupCode, cancellationToken); - if (!systemGroup.AllowOverride) - { - throw new BusinessException(ErrorCodes.Forbidden, "该系统字典不允许租户覆盖"); - } - - var config = await overrideRepository.GetAsync(tenantId, systemGroup.Id, cancellationToken); - if (config == null) - { - config = new TenantDictionaryOverride - { - TenantId = tenantId, - SystemDictionaryGroupId = systemGroup.Id, - OverrideEnabled = true, - HiddenSystemItemIds = Array.Empty(), - CustomSortOrder = "{}" - }; - await overrideRepository.AddAsync(config, cancellationToken); - } - else - { - config.OverrideEnabled = true; - await overrideRepository.UpdateAsync(config, cancellationToken); - } - - await overrideRepository.SaveChangesAsync(cancellationToken); - await cache.InvalidateAsync( - DictionaryCacheKeys.BuildDictionaryKey(tenantId, systemGroup.Code), - CacheInvalidationOperation.Update, - cancellationToken); - - return MapOverrideDto(config, systemGroup.Code); - } - - /// - /// 关闭覆盖配置。 - /// - public async Task DisableOverrideAsync(long tenantId, string systemGroupCode, CancellationToken cancellationToken = default) - { - if (tenantId == 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "租户上下文缺失"); - } - - var systemGroup = await RequireSystemGroupAsync(systemGroupCode, cancellationToken); - var config = await overrideRepository.GetAsync(tenantId, systemGroup.Id, cancellationToken); - if (config == null) - { - return false; - } - - config.OverrideEnabled = false; - await overrideRepository.UpdateAsync(config, cancellationToken); - await overrideRepository.SaveChangesAsync(cancellationToken); - await cache.InvalidateAsync( - DictionaryCacheKeys.BuildDictionaryKey(tenantId, systemGroup.Code), - CacheInvalidationOperation.Update, - cancellationToken); - - return true; - } - - /// - /// 更新隐藏系统字典项。 - /// - public async Task UpdateHiddenItemsAsync( - long tenantId, - string systemGroupCode, - long[] hiddenIds, - CancellationToken cancellationToken = default) - { - if (tenantId == 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "租户上下文缺失"); - } - - var systemGroup = await RequireSystemGroupAsync(systemGroupCode, cancellationToken); - if (!systemGroup.AllowOverride) - { - throw new BusinessException(ErrorCodes.Forbidden, "该系统字典不允许租户覆盖"); - } - - var systemItems = await itemRepository.GetByGroupIdAsync(0, systemGroup.Id, cancellationToken); - var validIds = systemItems.Select(item => item.Id).ToHashSet(); - var normalized = hiddenIds?.Distinct().ToArray() ?? Array.Empty(); - - if (normalized.Any(id => !validIds.Contains(id))) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "隐藏项包含无效的系统字典项"); - } - - var config = await overrideRepository.GetAsync(tenantId, systemGroup.Id, cancellationToken); - if (config == null) - { - config = new TenantDictionaryOverride - { - TenantId = tenantId, - SystemDictionaryGroupId = systemGroup.Id, - OverrideEnabled = true, - HiddenSystemItemIds = normalized, - CustomSortOrder = "{}" - }; - await overrideRepository.AddAsync(config, cancellationToken); - } - else - { - config.HiddenSystemItemIds = normalized; - await overrideRepository.UpdateAsync(config, cancellationToken); - } - - await overrideRepository.SaveChangesAsync(cancellationToken); - await cache.InvalidateAsync( - DictionaryCacheKeys.BuildDictionaryKey(tenantId, systemGroup.Code), - CacheInvalidationOperation.Update, - cancellationToken); - - return MapOverrideDto(config, systemGroup.Code); - } - - /// - /// 更新自定义排序配置。 - /// - public async Task UpdateCustomSortOrderAsync( - long tenantId, - string systemGroupCode, - Dictionary sortOrderMap, - CancellationToken cancellationToken = default) - { - if (tenantId == 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "租户上下文缺失"); - } - - var systemGroup = await RequireSystemGroupAsync(systemGroupCode, cancellationToken); - if (!systemGroup.AllowOverride) - { - throw new BusinessException(ErrorCodes.Forbidden, "该系统字典不允许租户覆盖"); - } - - var validIds = await CollectValidItemIdsAsync(tenantId, systemGroup, cancellationToken); - if (sortOrderMap.Keys.Any(id => !validIds.Contains(id))) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "排序配置包含无效的字典项"); - } - - var config = await overrideRepository.GetAsync(tenantId, systemGroup.Id, cancellationToken); - if (config == null) - { - config = new TenantDictionaryOverride - { - TenantId = tenantId, - SystemDictionaryGroupId = systemGroup.Id, - OverrideEnabled = true, - HiddenSystemItemIds = Array.Empty(), - CustomSortOrder = SerializeSortOrder(sortOrderMap) - }; - await overrideRepository.AddAsync(config, cancellationToken); - } - else - { - config.CustomSortOrder = SerializeSortOrder(sortOrderMap); - await overrideRepository.UpdateAsync(config, cancellationToken); - } - - await overrideRepository.SaveChangesAsync(cancellationToken); - await cache.InvalidateAsync( - DictionaryCacheKeys.BuildDictionaryKey(tenantId, systemGroup.Code), - CacheInvalidationOperation.Update, - cancellationToken); - - return MapOverrideDto(config, systemGroup.Code); - } - - private async Task> CollectValidItemIdsAsync(long tenantId, DictionaryGroup systemGroup, CancellationToken cancellationToken) - { - var validIds = (await itemRepository.GetByGroupIdAsync(0, systemGroup.Id, cancellationToken)) - .Select(item => item.Id) - .ToHashSet(); - - var tenantGroup = await groupRepository.GetByCodeAsync(tenantId, systemGroup.Code, cancellationToken); - if (tenantGroup != null) - { - foreach (var item in await itemRepository.GetByGroupIdAsync(tenantId, tenantGroup.Id, cancellationToken)) - { - validIds.Add(item.Id); - } - } - - return validIds; - } - - private async Task RequireSystemGroupAsync(string code, CancellationToken cancellationToken) - { - var normalized = new DictionaryCode(code); - var group = await groupRepository.GetByCodeAsync(0, normalized, cancellationToken); - if (group == null) - { - throw new BusinessException(ErrorCodes.NotFound, "系统字典分组不存在"); - } - - if (group.Scope != DictionaryScope.System) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "仅支持系统字典覆盖配置"); - } - - return group; - } - - private static OverrideConfigDto MapOverrideDto(TenantDictionaryOverride config, DictionaryCode systemCode) - { - return new OverrideConfigDto - { - TenantId = config.TenantId, - SystemDictionaryGroupCode = systemCode.Value, - OverrideEnabled = config.OverrideEnabled, - HiddenSystemItemIds = config.HiddenSystemItemIds, - CustomSortOrder = ParseSortOrder(config.CustomSortOrder) - }; - } - - private static Dictionary ParseSortOrder(string? json) - { - if (string.IsNullOrWhiteSpace(json)) - { - return new Dictionary(); - } - - try - { - return JsonSerializer.Deserialize>(json, JsonOptions) ?? new Dictionary(); - } - catch (JsonException) - { - return new Dictionary(); - } - } - - private static string SerializeSortOrder(Dictionary map) - => JsonSerializer.Serialize(map ?? new Dictionary(), JsonOptions); -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryQueryService.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryQueryService.cs deleted file mode 100644 index 3d33d0d..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryQueryService.cs +++ /dev/null @@ -1,246 +0,0 @@ -using TakeoutSaaS.Application.Dictionary.Abstractions; -using TakeoutSaaS.Application.Dictionary.Contracts; -using TakeoutSaaS.Application.Dictionary.Models; -using TakeoutSaaS.Domain.Dictionary.Entities; -using TakeoutSaaS.Domain.Dictionary.Enums; -using TakeoutSaaS.Domain.Dictionary.Repositories; -using TakeoutSaaS.Domain.Dictionary.ValueObjects; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Results; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Dictionary.Services; - -/// -/// 字典查询服务。 -/// -public sealed class DictionaryQueryService( - IDictionaryGroupRepository groupRepository, - IDictionaryItemRepository itemRepository, - DictionaryMergeService mergeService, - IDictionaryHybridCache cache, - ITenantProvider tenantProvider) -{ - private static readonly TimeSpan CacheTtl = TimeSpan.FromMinutes(30); - - /// - /// 获取字典分组分页数据。 - /// - public async Task> GetGroupsAsync( - DictionaryGroupQuery query, - CancellationToken cancellationToken = default) - { - var tenantId = tenantProvider.GetCurrentTenantId(); - var scope = query.Scope ?? (tenantId == 0 ? DictionaryScope.System : DictionaryScope.Business); - var sortDescending = string.Equals(query.SortOrder, "desc", StringComparison.OrdinalIgnoreCase); - var targetTenant = scope == DictionaryScope.System ? 0 : tenantId; - - var cacheKey = DictionaryCacheKeys.BuildGroupKey( - targetTenant, - scope, - query.Page, - query.PageSize, - query.Keyword, - query.IsEnabled, - query.SortBy, - sortDescending); - - var cached = await cache.GetOrCreateAsync( - cacheKey, - CacheTtl, - async token => - { - var groups = await groupRepository.GetPagedAsync( - targetTenant, - scope, - query.Keyword, - query.IsEnabled, - query.Page, - query.PageSize, - query.SortBy, - sortDescending, - token); - - var total = await groupRepository.CountAsync( - targetTenant, - scope, - query.Keyword, - query.IsEnabled, - token); - - var items = new List(groups.Count); - foreach (var group in groups) - { - IReadOnlyList? groupItems = null; - if (query.IncludeItems) - { - var groupItemEntities = await itemRepository.GetByGroupIdAsync(group.TenantId, group.Id, token); - groupItems = groupItemEntities - .Where(item => item.IsEnabled) - .OrderBy(item => item.SortOrder) - .Select(DictionaryMapper.ToItemDto) - .ToList(); - } - - items.Add(DictionaryMapper.ToGroupDto(group, groupItems)); - } - - return new DictionaryGroupPage - { - Items = items, - Page = query.Page, - PageSize = query.PageSize, - TotalCount = total - }; - }, - cancellationToken); - - var page = cached ?? new DictionaryGroupPage - { - Items = Array.Empty(), - Page = query.Page, - PageSize = query.PageSize, - TotalCount = 0 - }; - - return new PagedResult(page.Items, page.Page, page.PageSize, page.TotalCount); - } - - /// - /// 获取字典分组详情。 - /// - public async Task GetGroupByIdAsync(long groupId, CancellationToken cancellationToken = default) - { - var group = await groupRepository.GetByIdAsync(groupId, cancellationToken); - if (group == null) - { - return null; - } - - EnsureGroupReadable(group); - return DictionaryMapper.ToGroupDto(group); - } - - /// - /// 获取分组下字典项列表。 - /// - public async Task> GetItemsByGroupIdAsync(long groupId, CancellationToken cancellationToken = default) - { - var cacheKey = DictionaryCacheKeys.BuildItemKey(groupId); - var cached = await cache.GetOrCreateAsync>( - cacheKey, - CacheTtl, - async token => - { - var group = await groupRepository.GetByIdAsync(groupId, token); - if (group == null) - { - throw new BusinessException(ErrorCodes.NotFound, "字典分组不存在"); - } - - EnsureGroupReadable(group); - var items = await itemRepository.GetByGroupIdAsync(group.TenantId, groupId, token); - return items - .Where(item => item.IsEnabled) - .OrderBy(item => item.SortOrder) - .Select(DictionaryMapper.ToItemDto) - .ToList(); - }, - cancellationToken); - - return cached ?? Array.Empty(); - } - - /// - /// 获取合并后的字典项列表。 - /// - public async Task> GetMergedDictionaryAsync(string code, CancellationToken cancellationToken = default) - { - if (!DictionaryCode.IsValid(code)) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "字典编码格式不正确"); - } - - var tenantId = tenantProvider.GetCurrentTenantId(); - var normalized = new DictionaryCode(code); - var cacheKey = DictionaryCacheKeys.BuildDictionaryKey(tenantId, normalized); - - var cached = await cache.GetOrCreateAsync>( - cacheKey, - CacheTtl, - async token => - { - var systemGroup = await groupRepository.GetByCodeAsync(0, normalized, token); - if (systemGroup == null || !systemGroup.IsEnabled) - { - return Array.Empty(); - } - - if (tenantId == 0) - { - var systemItems = await itemRepository.GetByGroupIdAsync(0, systemGroup.Id, token); - return systemItems - .Where(item => item.IsEnabled) - .OrderBy(item => item.SortOrder) - .Select(DictionaryMapper.ToItemDto) - .ToList(); - } - - return await mergeService.MergeItemsAsync(tenantId, systemGroup.Id, token); - }, - cancellationToken); - - return cached ?? Array.Empty(); - } - - /// - /// 批量获取字典项。 - /// - public async Task>> BatchGetDictionariesAsync( - IEnumerable codes, - CancellationToken cancellationToken = default) - { - var normalizedCodes = codes - .Where(DictionaryCode.IsValid) - .Select(code => new DictionaryCode(code).Value) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToArray(); - - var result = new Dictionary>(StringComparer.OrdinalIgnoreCase); - if (normalizedCodes.Length == 0) - { - return result; - } - - var tasks = normalizedCodes.Select(async code => - { - var items = await GetMergedDictionaryAsync(code, cancellationToken); - return (code, items); - }); - - foreach (var pair in await Task.WhenAll(tasks)) - { - result[pair.code] = pair.items; - } - - return result; - } - - private void EnsureGroupReadable(DictionaryGroup group) - { - var tenantId = tenantProvider.GetCurrentTenantId(); - if (tenantId != 0 && group.Scope == DictionaryScope.Business && group.TenantId != tenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "无权访问其他租户字典"); - } - } - - private sealed class DictionaryGroupPage - { - public IReadOnlyList Items { get; init; } = Array.Empty(); - public int Page { get; init; } - public int PageSize { get; init; } - public int TotalCount { get; init; } - } -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryValueConverter.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryValueConverter.cs deleted file mode 100644 index 7fe46a2..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryValueConverter.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Text.Json; -using TakeoutSaaS.Domain.Dictionary.ValueObjects; - -namespace TakeoutSaaS.Application.Dictionary.Services; - -/// -/// 字典值序列化与反序列化辅助。 -/// -internal static class DictionaryValueConverter -{ - /// - /// 将多语言字典序列化为 JSON。 - /// - public static string Serialize(Dictionary values) - { - var i18n = new I18nValue(values); - return i18n.ToJson(); - } - - /// - /// 将 JSON 解析为多语言字典。 - /// - public static Dictionary Deserialize(string? json) - { - if (string.IsNullOrWhiteSpace(json)) - { - return new Dictionary(StringComparer.OrdinalIgnoreCase); - } - - try - { - return I18nValue.FromJson(json).ToDictionary(); - } - catch (JsonException) - { - return new Dictionary(StringComparer.OrdinalIgnoreCase) - { - ["zh-CN"] = json.Trim() - }; - } - catch (ArgumentException) - { - return new Dictionary(StringComparer.OrdinalIgnoreCase); - } - } -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Validators/CreateDictionaryGroupValidator.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Validators/CreateDictionaryGroupValidator.cs deleted file mode 100644 index 024e6ca..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Validators/CreateDictionaryGroupValidator.cs +++ /dev/null @@ -1,25 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.Dictionary.Contracts; - -namespace TakeoutSaaS.Application.Dictionary.Validators; - -/// -/// 创建字典分组请求验证器。 -/// -public sealed class CreateDictionaryGroupValidator : AbstractValidator -{ - public CreateDictionaryGroupValidator() - { - RuleFor(x => x.Code) - .NotEmpty() - .Length(2, 64) - .Matches("^[a-zA-Z0-9_]+$"); - - RuleFor(x => x.Name) - .NotEmpty() - .MaximumLength(128); - - RuleFor(x => x.Scope) - .IsInEnum(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Validators/I18nValueValidator.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Validators/I18nValueValidator.cs deleted file mode 100644 index 2fdb6ef..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Validators/I18nValueValidator.cs +++ /dev/null @@ -1,32 +0,0 @@ -using FluentValidation; - -namespace TakeoutSaaS.Application.Dictionary.Validators; - -/// -/// 多语言值校验器。 -/// -public sealed class I18nValueValidator : AbstractValidator> -{ - public I18nValueValidator() - { - RuleFor(x => x) - .NotNull() - .Must(HasAtLeastOneValue) - .WithMessage("至少需要提供一种语言的值。"); - - RuleForEach(x => x.Keys) - .NotEmpty() - .Matches("^[a-zA-Z]{2,5}(-[a-zA-Z]{2,5})?$") - .WithMessage("语言代码格式不正确。"); - } - - private static bool HasAtLeastOneValue(Dictionary? values) - { - if (values == null || values.Count == 0) - { - return false; - } - - return values.Any(pair => !string.IsNullOrWhiteSpace(pair.Value)); - } -} diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Validators/UpdateDictionaryItemValidator.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Validators/UpdateDictionaryItemValidator.cs deleted file mode 100644 index 4de9c23..0000000 --- a/src/Application/TakeoutSaaS.Application/Dictionary/Validators/UpdateDictionaryItemValidator.cs +++ /dev/null @@ -1,23 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.Dictionary.Contracts; - -namespace TakeoutSaaS.Application.Dictionary.Validators; - -/// -/// 更新字典项请求验证器。 -/// -public sealed class UpdateDictionaryItemValidator : AbstractValidator -{ - public UpdateDictionaryItemValidator() - { - RuleFor(x => x.Key) - .NotEmpty() - .MaximumLength(128); - - RuleFor(x => x.Value) - .SetValidator(new I18nValueValidator()); - - RuleFor(x => x.SortOrder) - .GreaterThanOrEqualTo(0); - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Abstractions/IAdminPasswordResetTokenStore.cs b/src/Application/TakeoutSaaS.Application/Identity/Abstractions/IAdminPasswordResetTokenStore.cs deleted file mode 100644 index c83e6fc..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Abstractions/IAdminPasswordResetTokenStore.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace TakeoutSaaS.Application.Identity.Abstractions; - -/// -/// 管理后台“重置密码链接”令牌存储。 -/// -public interface IAdminPasswordResetTokenStore -{ - /// - /// 签发一次性重置令牌。 - /// - /// 目标用户 ID。 - /// 过期时间(UTC)。 - /// 取消标记。 - /// 令牌值。 - Task IssueAsync(long userId, DateTime expiresAt, CancellationToken cancellationToken = default); - - /// - /// 消费一次性重置令牌(成功后即删除)。 - /// - /// 令牌值。 - /// 取消标记。 - /// 令牌绑定的用户 ID;不存在/过期返回 null。 - Task ConsumeAsync(string token, CancellationToken cancellationToken = default); -} - diff --git a/src/Application/TakeoutSaaS.Application/Identity/Abstractions/IIdentityOperationLogPublisher.cs b/src/Application/TakeoutSaaS.Application/Identity/Abstractions/IIdentityOperationLogPublisher.cs deleted file mode 100644 index 2b0add6..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Abstractions/IIdentityOperationLogPublisher.cs +++ /dev/null @@ -1,17 +0,0 @@ -using TakeoutSaaS.Application.Identity.Events; - -namespace TakeoutSaaS.Application.Identity.Abstractions; - -/// -/// 身份模块操作日志发布器。 -/// -public interface IIdentityOperationLogPublisher -{ - /// - /// 发布身份模块操作日志消息。 - /// - /// 操作日志消息。 - /// 取消标记。 - /// 异步任务。 - Task PublishAsync(IdentityUserOperationLogMessage message, CancellationToken cancellationToken = default); -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Abstractions/ILoginRateLimiter.cs b/src/Application/TakeoutSaaS.Application/Identity/Abstractions/ILoginRateLimiter.cs deleted file mode 100644 index 66f91a9..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Abstractions/ILoginRateLimiter.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace TakeoutSaaS.Application.Identity.Abstractions; - -/// -/// 登录限流器。 -/// -public interface ILoginRateLimiter -{ - Task EnsureAllowedAsync(string key, CancellationToken cancellationToken = default); - Task ResetAsync(string key, CancellationToken cancellationToken = default); -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Abstractions/IMiniAuthService.cs b/src/Application/TakeoutSaaS.Application/Identity/Abstractions/IMiniAuthService.cs deleted file mode 100644 index 8c5250a..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Abstractions/IMiniAuthService.cs +++ /dev/null @@ -1,13 +0,0 @@ -using TakeoutSaaS.Application.Identity.Contracts; - -namespace TakeoutSaaS.Application.Identity.Abstractions; - -/// -/// 小程序认证服务。 -/// -public interface IMiniAuthService -{ - Task LoginWithWeChatAsync(WeChatLoginRequest request, CancellationToken cancellationToken = default); - Task RefreshTokenAsync(RefreshTokenRequest request, CancellationToken cancellationToken = default); - Task GetProfileAsync(long userId, CancellationToken cancellationToken = default); -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Abstractions/IWeChatAuthService.cs b/src/Application/TakeoutSaaS.Application/Identity/Abstractions/IWeChatAuthService.cs deleted file mode 100644 index d3465ef..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Abstractions/IWeChatAuthService.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace TakeoutSaaS.Application.Identity.Abstractions; - -/// -/// 微信 code2Session 服务契约。 -/// -public interface IWeChatAuthService -{ - /// - /// 调用微信接口完成 code2Session 交换。 - /// - /// 临时登录凭证 code。 - /// 取消标记。 - /// 会话信息。 - Task Code2SessionAsync(string code, CancellationToken cancellationToken = default); -} - -/// -/// 微信会话信息。 -/// -public sealed class WeChatSessionInfo -{ - /// - /// OpenId。 - /// - public string OpenId { get; init; } = string.Empty; - - /// - /// UnionId。 - /// - public string? UnionId { get; init; } - - /// - /// 会话密钥。 - /// - public string SessionKey { get; init; } = string.Empty; -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/AssignUserRolesCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/AssignUserRolesCommand.cs deleted file mode 100644 index c52bbff..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/AssignUserRolesCommand.cs +++ /dev/null @@ -1,19 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.Identity.Commands; - -/// -/// 为用户分配角色(覆盖式)。 -/// -public sealed record AssignUserRolesCommand : IRequest -{ - /// - /// 用户 ID。 - /// - public long UserId { get; init; } - - /// - /// 角色 ID 集合。 - /// - public long[] RoleIds { get; init; } = Array.Empty(); -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/BatchIdentityUserOperationCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/BatchIdentityUserOperationCommand.cs deleted file mode 100644 index 827e1ed..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/BatchIdentityUserOperationCommand.cs +++ /dev/null @@ -1,26 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Application.Identity.Models; - -namespace TakeoutSaaS.Application.Identity.Commands; - -/// -/// 批量用户操作命令。 -/// -public sealed record BatchIdentityUserOperationCommand : IRequest -{ - /// - /// 目标租户 ID(可选,默认当前登录租户;禁止跨租户操作)。 - /// - public long? TenantId { get; init; } - - /// - /// 操作类型。 - /// - public IdentityUserBatchOperation Operation { get; init; } - - /// - /// 用户 ID 列表(字符串)。 - /// - public string[] UserIds { get; init; } = Array.Empty(); -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/BindRolePermissionsCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/BindRolePermissionsCommand.cs deleted file mode 100644 index 51eb4bf..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/BindRolePermissionsCommand.cs +++ /dev/null @@ -1,24 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.Identity.Commands; - -/// -/// 绑定角色权限(覆盖式)。 -/// -public sealed record BindRolePermissionsCommand : IRequest -{ - /// - /// 角色 ID。 - /// - public long RoleId { get; init; } - - /// - /// 租户 ID(可选,空则取当前上下文)。 - /// - public long? TenantId { get; init; } - - /// - /// 权限 ID 集合。 - /// - public long[] PermissionIds { get; init; } = Array.Empty(); -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/ChangeIdentityUserStatusCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/ChangeIdentityUserStatusCommand.cs deleted file mode 100644 index 1e6dd30..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/ChangeIdentityUserStatusCommand.cs +++ /dev/null @@ -1,25 +0,0 @@ -using MediatR; -using TakeoutSaaS.Domain.Identity.Enums; - -namespace TakeoutSaaS.Application.Identity.Commands; - -/// -/// 更新用户状态命令。 -/// -public sealed record ChangeIdentityUserStatusCommand : IRequest -{ - /// - /// 用户 ID。 - /// - public long UserId { get; init; } - - /// - /// 目标租户 ID(可选,默认当前登录租户;禁止跨租户操作)。 - /// - public long? TenantId { get; init; } - - /// - /// 目标状态。 - /// - public IdentityUserStatus Status { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/CloneRoleTemplateCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/CloneRoleTemplateCommand.cs deleted file mode 100644 index bf60e8a..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/CloneRoleTemplateCommand.cs +++ /dev/null @@ -1,40 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; - -namespace TakeoutSaaS.Application.Identity.Commands; - -/// -/// 克隆角色模板。 -/// -public sealed record CloneRoleTemplateCommand : IRequest -{ - /// - /// 源模板编码。 - /// - public string SourceTemplateCode { get; init; } = string.Empty; - - /// - /// 新模板编码。 - /// - public string NewTemplateCode { get; init; } = string.Empty; - - /// - /// 新模板名称(为空则沿用源模板)。 - /// - public string? Name { get; init; } - - /// - /// 新模板描述(为空则沿用源模板)。 - /// - public string? Description { get; init; } - - /// - /// 是否启用(为空则沿用源模板)。 - /// - public bool? IsActive { get; init; } - - /// - /// 权限编码集合(为空则沿用源模板权限)。 - /// - public IReadOnlyCollection? PermissionCodes { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/CopyRoleTemplateCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/CopyRoleTemplateCommand.cs deleted file mode 100644 index efaa1a3..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/CopyRoleTemplateCommand.cs +++ /dev/null @@ -1,30 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; - -namespace TakeoutSaaS.Application.Identity.Commands; - -/// -/// 从预置模板复制角色并绑定权限。 -/// -public sealed record CopyRoleTemplateCommand : IRequest -{ - /// - /// 模板编码。 - /// - public string TemplateCode { get; init; } = string.Empty; - - /// - /// 复制后角色名称(为空则使用模板名称)。 - /// - public string? RoleName { get; init; } - - /// - /// 复制后角色编码(为空则使用模板编码)。 - /// - public string? RoleCode { get; init; } - - /// - /// 角色描述(为空则沿用模板描述)。 - /// - public string? Description { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/CreateIdentityUserCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/CreateIdentityUserCommand.cs deleted file mode 100644 index e528df1..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/CreateIdentityUserCommand.cs +++ /dev/null @@ -1,66 +0,0 @@ -using MediatR; -using System.ComponentModel.DataAnnotations; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Domain.Identity.Enums; - -namespace TakeoutSaaS.Application.Identity.Commands; - -/// -/// 创建用户命令。 -/// -public sealed record CreateIdentityUserCommand : IRequest -{ - /// - /// 目标租户 ID(可选,默认当前登录租户;禁止跨租户操作)。 - /// - public long? TenantId { get; init; } - - /// - /// 登录账号。 - /// - [Required] - [StringLength(64)] - public string Account { get; init; } = string.Empty; - - /// - /// 展示名称。 - /// - [Required] - [StringLength(64)] - public string DisplayName { get; init; } = string.Empty; - - /// - /// 初始密码。 - /// - [Required] - [StringLength(32, MinimumLength = 6)] - public string Password { get; init; } = string.Empty; - - /// - /// 手机号。 - /// - [StringLength(32)] - public string? Phone { get; init; } - - /// - /// 邮箱。 - /// - [StringLength(128)] - public string? Email { get; init; } - - /// - /// 头像地址。 - /// - [StringLength(512)] - public string? Avatar { get; init; } - - /// - /// 角色 ID 列表(字符串)。 - /// - public string[] RoleIds { get; init; } = Array.Empty(); - - /// - /// 初始状态。 - /// - public IdentityUserStatus? Status { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/CreateMenuCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/CreateMenuCommand.cs deleted file mode 100644 index 8366de2..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/CreateMenuCommand.cs +++ /dev/null @@ -1,81 +0,0 @@ -using MediatR; -using System.Collections.Generic; -using TakeoutSaaS.Application.Identity.Contracts; - -namespace TakeoutSaaS.Application.Identity.Commands; - -/// -/// 创建菜单命令。 -/// -public sealed record CreateMenuCommand : IRequest -{ - /// - /// 父级菜单 ID。 - /// - public long ParentId { get; init; } - - /// - /// 菜单名称。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 路由路径。 - /// - public string Path { get; init; } = string.Empty; - - /// - /// 前端组件路径。 - /// - public string Component { get; init; } = string.Empty; - - /// - /// 显示标题。 - /// - public string Title { get; init; } = string.Empty; - - /// - /// 图标。 - /// - public string? Icon { get; init; } - - /// - /// 是否外链。 - /// - public bool IsIframe { get; init; } - - /// - /// 外链地址。 - /// - public string? Link { get; init; } - - /// - /// 是否缓存。 - /// - public bool KeepAlive { get; init; } - - /// - /// 排序序号。 - /// - public int SortOrder { get; init; } - - /// - /// 访问所需权限。 - /// - public IReadOnlyCollection RequiredPermissions { get; init; } = []; - - /// - /// 元信息权限。 - /// - public IReadOnlyCollection MetaPermissions { get; init; } = []; - - /// - /// 元信息角色。 - /// - public IReadOnlyCollection MetaRoles { get; init; } = []; - - /// - /// 按钮权限集合。 - /// - public IReadOnlyCollection AuthList { get; init; } = []; -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/CreatePermissionCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/CreatePermissionCommand.cs deleted file mode 100644 index 80d1587..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/CreatePermissionCommand.cs +++ /dev/null @@ -1,40 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; - -namespace TakeoutSaaS.Application.Identity.Commands; - -/// -/// 创建权限。 -/// -public sealed record CreatePermissionCommand : IRequest -{ - /// - /// 父级权限 ID。 - /// - public long ParentId { get; init; } = 0; - - /// - /// 排序序号。 - /// - public int SortOrder { get; init; } = 0; - - /// - /// 权限类型(group/leaf)。 - /// - public string Type { get; init; } = "leaf"; - - /// - /// 权限名称。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 权限编码。 - /// - public string Code { get; init; } = string.Empty; - - /// - /// 描述。 - /// - public string? Description { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/CreateRoleCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/CreateRoleCommand.cs deleted file mode 100644 index d6318c5..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/CreateRoleCommand.cs +++ /dev/null @@ -1,30 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; - -namespace TakeoutSaaS.Application.Identity.Commands; - -/// -/// 创建角色。 -/// -public sealed record CreateRoleCommand : IRequest -{ - /// - /// 租户 ID(空则取当前上下文)。 - /// - public long? TenantId { get; init; } - - /// - /// 角色名称。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 角色编码。 - /// - public string Code { get; init; } = string.Empty; - - /// - /// 描述。 - /// - public string? Description { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/CreateRoleTemplateCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/CreateRoleTemplateCommand.cs deleted file mode 100644 index de2bd4c..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/CreateRoleTemplateCommand.cs +++ /dev/null @@ -1,35 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; - -namespace TakeoutSaaS.Application.Identity.Commands; - -/// -/// 创建角色模板命令。 -/// -public sealed record CreateRoleTemplateCommand : IRequest -{ - /// - /// 模板编码。 - /// - public string TemplateCode { get; init; } = string.Empty; - - /// - /// 模板名称。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 模板描述。 - /// - public string? Description { get; init; } - - /// - /// 是否启用。 - /// - public bool IsActive { get; init; } = true; - - /// - /// 权限编码集合。 - /// - public IReadOnlyCollection PermissionCodes { get; init; } = Array.Empty(); -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/DeleteIdentityUserCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/DeleteIdentityUserCommand.cs deleted file mode 100644 index bf056f6..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/DeleteIdentityUserCommand.cs +++ /dev/null @@ -1,19 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.Identity.Commands; - -/// -/// 删除用户命令。 -/// -public sealed record DeleteIdentityUserCommand : IRequest -{ - /// - /// 用户 ID。 - /// - public long UserId { get; init; } - - /// - /// 目标租户 ID(可选,默认当前登录租户;禁止跨租户操作)。 - /// - public long? TenantId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/DeleteMenuCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/DeleteMenuCommand.cs deleted file mode 100644 index 3b3baca..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/DeleteMenuCommand.cs +++ /dev/null @@ -1,14 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.Identity.Commands; - -/// -/// 删除菜单命令。 -/// -public sealed record DeleteMenuCommand : IRequest -{ - /// - /// 菜单 ID。 - /// - public long Id { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/DeletePermissionCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/DeletePermissionCommand.cs deleted file mode 100644 index 172d79c..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/DeletePermissionCommand.cs +++ /dev/null @@ -1,14 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.Identity.Commands; - -/// -/// 删除权限。 -/// -public sealed record DeletePermissionCommand : IRequest -{ - /// - /// 权限 ID。 - /// - public long PermissionId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/DeleteRoleCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/DeleteRoleCommand.cs deleted file mode 100644 index d23a216..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/DeleteRoleCommand.cs +++ /dev/null @@ -1,19 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.Identity.Commands; - -/// -/// 删除角色。 -/// -public sealed record DeleteRoleCommand : IRequest -{ - /// - /// 角色 ID。 - /// - public long RoleId { get; init; } - - /// - /// 租户 ID(空则取当前上下文)。 - /// - public long? TenantId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/DeleteRoleTemplateCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/DeleteRoleTemplateCommand.cs deleted file mode 100644 index 7f29db6..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/DeleteRoleTemplateCommand.cs +++ /dev/null @@ -1,14 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.Identity.Commands; - -/// -/// 删除角色模板命令。 -/// -public sealed record DeleteRoleTemplateCommand : IRequest -{ - /// - /// 模板编码。 - /// - public string TemplateCode { get; init; } = string.Empty; -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/InitializeRoleTemplatesCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/InitializeRoleTemplatesCommand.cs deleted file mode 100644 index 7eb39f9..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/InitializeRoleTemplatesCommand.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; - -namespace TakeoutSaaS.Application.Identity.Commands; - -/// -/// 批量为当前租户初始化角色模板。 -/// -public sealed record InitializeRoleTemplatesCommand : IRequest> -{ - /// - /// 需要初始化的模板编码列表(为空则全部)。 - /// - public IReadOnlyCollection? TemplateCodes { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/ResetAdminPasswordByTokenCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/ResetAdminPasswordByTokenCommand.cs deleted file mode 100644 index 52bdb13..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/ResetAdminPasswordByTokenCommand.cs +++ /dev/null @@ -1,20 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.Identity.Commands; - -/// -/// 通过重置链接令牌重置管理员密码命令。 -/// -public sealed record ResetAdminPasswordByTokenCommand : IRequest -{ - /// - /// 一次性重置令牌。 - /// - public required string Token { get; init; } - - /// - /// 新密码(明文,仅用于服务端哈希)。 - /// - public required string NewPassword { get; init; } -} - diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/ResetIdentityUserPasswordCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/ResetIdentityUserPasswordCommand.cs deleted file mode 100644 index 9cda914..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/ResetIdentityUserPasswordCommand.cs +++ /dev/null @@ -1,20 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; - -namespace TakeoutSaaS.Application.Identity.Commands; - -/// -/// 生成用户重置密码链接命令。 -/// -public sealed record ResetIdentityUserPasswordCommand : IRequest -{ - /// - /// 用户 ID。 - /// - public long UserId { get; init; } - - /// - /// 目标租户 ID(可选,默认当前登录租户;禁止跨租户操作)。 - /// - public long? TenantId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/RestoreIdentityUserCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/RestoreIdentityUserCommand.cs deleted file mode 100644 index c28ae28..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/RestoreIdentityUserCommand.cs +++ /dev/null @@ -1,19 +0,0 @@ -using MediatR; - -namespace TakeoutSaaS.Application.Identity.Commands; - -/// -/// 恢复用户命令。 -/// -public sealed record RestoreIdentityUserCommand : IRequest -{ - /// - /// 用户 ID。 - /// - public long UserId { get; init; } - - /// - /// 目标租户 ID(可选,默认当前登录租户;禁止跨租户操作)。 - /// - public long? TenantId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/UpdateIdentityUserCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/UpdateIdentityUserCommand.cs deleted file mode 100644 index 1aeb098..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/UpdateIdentityUserCommand.cs +++ /dev/null @@ -1,56 +0,0 @@ -using MediatR; -using System.ComponentModel.DataAnnotations; -using TakeoutSaaS.Application.Identity.Contracts; - -namespace TakeoutSaaS.Application.Identity.Commands; - -/// -/// 更新用户命令。 -/// -public sealed record UpdateIdentityUserCommand : IRequest -{ - /// - /// 用户 ID。 - /// - public long UserId { get; init; } - - /// - /// 目标租户 ID(可选,默认当前登录租户;禁止跨租户操作)。 - /// - public long? TenantId { get; init; } - - /// - /// 展示名称。 - /// - [Required] - [StringLength(64)] - public string DisplayName { get; init; } = string.Empty; - - /// - /// 手机号。 - /// - [StringLength(32)] - public string? Phone { get; init; } - - /// - /// 邮箱。 - /// - [StringLength(128)] - public string? Email { get; init; } - - /// - /// 头像地址。 - /// - [StringLength(512)] - public string? Avatar { get; init; } - - /// - /// 角色 ID 列表(字符串)。 - /// - public string[]? RoleIds { get; init; } - - /// - /// 并发控制版本(兼容字段,当前由数据库 xmin 托管)。 - /// - public byte[]? RowVersion { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/UpdateMenuCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/UpdateMenuCommand.cs deleted file mode 100644 index dd28eea..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/UpdateMenuCommand.cs +++ /dev/null @@ -1,86 +0,0 @@ -using MediatR; -using System.Collections.Generic; -using TakeoutSaaS.Application.Identity.Contracts; - -namespace TakeoutSaaS.Application.Identity.Commands; - -/// -/// 更新菜单命令。 -/// -public sealed record UpdateMenuCommand : IRequest -{ - /// - /// 菜单 ID。 - /// - public long Id { get; init; } - - /// - /// 父级菜单 ID。 - /// - public long ParentId { get; init; } - - /// - /// 菜单名称。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 路由路径。 - /// - public string Path { get; init; } = string.Empty; - - /// - /// 前端组件路径。 - /// - public string Component { get; init; } = string.Empty; - - /// - /// 显示标题。 - /// - public string Title { get; init; } = string.Empty; - - /// - /// 图标。 - /// - public string? Icon { get; init; } - - /// - /// 是否外链。 - /// - public bool IsIframe { get; init; } - - /// - /// 外链地址。 - /// - public string? Link { get; init; } - - /// - /// 是否缓存。 - /// - public bool KeepAlive { get; init; } - - /// - /// 排序序号。 - /// - public int SortOrder { get; init; } - - /// - /// 访问所需权限。 - /// - public IReadOnlyCollection RequiredPermissions { get; init; } = []; - - /// - /// 元信息权限。 - /// - public IReadOnlyCollection MetaPermissions { get; init; } = []; - - /// - /// 元信息角色。 - /// - public IReadOnlyCollection MetaRoles { get; init; } = []; - - /// - /// 按钮权限集合。 - /// - public IReadOnlyCollection AuthList { get; init; } = []; -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/UpdatePermissionCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/UpdatePermissionCommand.cs deleted file mode 100644 index 0f85127..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/UpdatePermissionCommand.cs +++ /dev/null @@ -1,40 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; - -namespace TakeoutSaaS.Application.Identity.Commands; - -/// -/// 更新权限。 -/// -public sealed record UpdatePermissionCommand : IRequest -{ - /// - /// 权限 ID。 - /// - public long PermissionId { get; init; } - - /// - /// 父级权限 ID。 - /// - public long ParentId { get; init; } - - /// - /// 排序序号。 - /// - public int SortOrder { get; init; } - - /// - /// 权限类型(group/leaf)。 - /// - public string Type { get; init; } = "leaf"; - - /// - /// 权限名称。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 描述。 - /// - public string? Description { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/UpdateRoleCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/UpdateRoleCommand.cs deleted file mode 100644 index caa5d0d..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/UpdateRoleCommand.cs +++ /dev/null @@ -1,30 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; - -namespace TakeoutSaaS.Application.Identity.Commands; - -/// -/// 更新角色。 -/// -public sealed record UpdateRoleCommand : IRequest -{ - /// - /// 角色 ID。 - /// - public long RoleId { get; init; } - - /// - /// 租户 ID(空则取当前上下文)。 - /// - public long? TenantId { get; init; } - - /// - /// 角色名称。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 角色描述。 - /// - public string? Description { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/UpdateRoleTemplateCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/UpdateRoleTemplateCommand.cs deleted file mode 100644 index ee6d5bf..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/UpdateRoleTemplateCommand.cs +++ /dev/null @@ -1,35 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; - -namespace TakeoutSaaS.Application.Identity.Commands; - -/// -/// 更新角色模板命令。 -/// -public sealed record UpdateRoleTemplateCommand : IRequest -{ - /// - /// 模板编码(路径参数)。 - /// - public string TemplateCode { get; init; } = string.Empty; - - /// - /// 模板名称。 - /// - public string Name { get; init; } = string.Empty; - - /// - /// 模板描述。 - /// - public string? Description { get; init; } - - /// - /// 是否启用。 - /// - public bool IsActive { get; init; } = true; - - /// - /// 权限编码集合。 - /// - public IReadOnlyCollection PermissionCodes { get; init; } = Array.Empty(); -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Events/IdentityUserOperationLogMessage.cs b/src/Application/TakeoutSaaS.Application/Identity/Events/IdentityUserOperationLogMessage.cs deleted file mode 100644 index 611a3b9..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Events/IdentityUserOperationLogMessage.cs +++ /dev/null @@ -1,47 +0,0 @@ -namespace TakeoutSaaS.Application.Identity.Events; - -/// -/// 身份用户操作日志消息。 -/// -public sealed record IdentityUserOperationLogMessage -{ - /// - /// 操作类型。 - /// - public string OperationType { get; init; } = string.Empty; - - /// - /// 目标类型。 - /// - public string TargetType { get; init; } = string.Empty; - - /// - /// 目标 ID 列表(JSON)。 - /// - public string? TargetIds { get; init; } - - /// - /// 操作人 ID。 - /// - public string? OperatorId { get; init; } - - /// - /// 操作人名称。 - /// - public string? OperatorName { get; init; } - - /// - /// 操作参数(JSON)。 - /// - public string? Parameters { get; init; } - - /// - /// 操作结果(JSON)。 - /// - public string? Result { get; init; } - - /// - /// 是否成功。 - /// - public bool Success { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Extensions/IdentityServiceCollectionExtensions.cs b/src/Application/TakeoutSaaS.Application/Identity/Extensions/IdentityServiceCollectionExtensions.cs deleted file mode 100644 index c5df667..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Extensions/IdentityServiceCollectionExtensions.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using TakeoutSaaS.Application.Identity.Abstractions; -using TakeoutSaaS.Application.Identity.Services; - -namespace TakeoutSaaS.Application.Identity.Extensions; - -/// -/// 应用层身份认证服务注入 -/// -public static class IdentityServiceCollectionExtensions -{ - /// - /// 注册身份认证相关应用服务 - /// - /// 服务集合 - /// 是否注册小程序认证服务 - public static IServiceCollection AddIdentityApplication(this IServiceCollection services, bool enableMiniSupport = false) - { - services.AddScoped(); - - if (enableMiniSupport) - { - services.AddScoped(); - } - - return services; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/AssignUserRolesCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/AssignUserRolesCommandHandler.cs deleted file mode 100644 index df00a53..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/AssignUserRolesCommandHandler.cs +++ /dev/null @@ -1,34 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Commands; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 用户角色分配处理器。 -/// -public sealed class AssignUserRolesCommandHandler( - IUserRoleRepository userRoleRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - /// 处理用户角色分配请求。 - /// - /// 分配命令。 - /// 取消标记。 - /// 执行结果。 - public async Task Handle(AssignUserRolesCommand request, CancellationToken cancellationToken) - { - // 1. 获取租户上下文 - var tenantId = tenantProvider.GetCurrentTenantId(); - - // 2. 覆盖式绑定角色 - await userRoleRepository.ReplaceUserRolesAsync(tenantId, request.UserId, request.RoleIds, cancellationToken); - await userRoleRepository.SaveChangesAsync(cancellationToken); - - // 3. 返回执行结果 - return true; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/BatchIdentityUserOperationCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/BatchIdentityUserOperationCommandHandler.cs deleted file mode 100644 index 1d88f67..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/BatchIdentityUserOperationCommandHandler.cs +++ /dev/null @@ -1,314 +0,0 @@ -using MediatR; -using System.Text.Json; -using TakeoutSaaS.Application.Identity.Abstractions; -using TakeoutSaaS.Application.Identity.Commands; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Application.Identity.Events; -using TakeoutSaaS.Application.Identity.Models; -using TakeoutSaaS.Domain.Identity.Entities; -using TakeoutSaaS.Domain.Identity.Enums; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 批量用户操作处理器。 -/// -public sealed class BatchIdentityUserOperationCommandHandler( - IIdentityUserRepository identityUserRepository, - IUserRoleRepository userRoleRepository, - IRoleRepository roleRepository, - ITenantProvider tenantProvider, - ICurrentUserAccessor currentUserAccessor, - IAdminAuthService adminAuthService, - IIdentityOperationLogPublisher operationLogPublisher) - : IRequestHandler -{ - /// - public async Task Handle(BatchIdentityUserOperationCommand request, CancellationToken cancellationToken) - { - // 1. 获取当前租户与操作者档案 - var currentTenantId = tenantProvider.GetCurrentTenantId(); - var operatorProfile = await adminAuthService.GetProfileAsync(currentUserAccessor.UserId, cancellationToken); - - // 2. 校验跨租户访问 - if (request.TenantId.HasValue && request.TenantId.Value != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户批量操作用户"); - } - - // 3. 解析用户 ID 列表 - var tenantId = currentTenantId; - var userIds = ParseIds(request.UserIds, "用户"); - if (userIds.Length == 0) - { - return new BatchIdentityUserOperationResult - { - SuccessCount = 0, - FailureCount = 0, - Failures = Array.Empty(), - ExportItems = Array.Empty() - }; - } - - // 4. 查询目标用户集合 - var includeDeleted = request.Operation == IdentityUserBatchOperation.Restore; - var users = await identityUserRepository.GetForUpdateByIdsAsync(tenantId, userIds, includeDeleted, cancellationToken); - var usersById = users.ToDictionary(user => user.Id, user => user, EqualityComparer.Default); - - // 5. 预计算租户管理员约束 - var tenantAdminRole = await roleRepository.FindByCodeAsync("tenant-admin", tenantId, cancellationToken); - var tenantAdminUserIds = tenantAdminRole == null - ? Array.Empty() - : (await userRoleRepository.GetByUserIdsAsync(tenantId, usersById.Keys, cancellationToken)) - .Where(x => x.RoleId == tenantAdminRole.Id) - .Select(x => x.UserId) - .Distinct() - .ToArray(); - var activeAdminCount = tenantAdminRole == null - ? 0 - : (await identityUserRepository.SearchPagedAsync(new IdentityUserSearchFilter - { - TenantId = tenantId, - RoleId = tenantAdminRole.Id, - Status = IdentityUserStatus.Active, - IncludeDeleted = false, - Page = 1, - PageSize = 1 - }, cancellationToken)).Total; - var remainingActiveAdmins = activeAdminCount; - - // 6. 执行批量操作 - var failures = new List(); - var successCount = 0; - var exportItems = new List(); - foreach (var userId in userIds) - { - if (!usersById.TryGetValue(userId, out var user)) - { - failures.Add(new BatchIdentityUserFailureItem - { - UserId = userId, - Reason = "用户不存在" - }); - continue; - } - - try - { - switch (request.Operation) - { - case IdentityUserBatchOperation.Enable: - user.Status = IdentityUserStatus.Active; - user.LockedUntil = null; - user.FailedLoginCount = 0; - await identityUserRepository.SaveChangesAsync(cancellationToken); - successCount++; - break; - case IdentityUserBatchOperation.Disable: - if (user.Status == IdentityUserStatus.Active - && tenantAdminUserIds.Contains(user.Id) - && remainingActiveAdmins <= 1) - { - throw new BusinessException(ErrorCodes.Conflict, "至少保留一个管理员"); - } - - if (user.Status == IdentityUserStatus.Active && tenantAdminUserIds.Contains(user.Id)) - { - remainingActiveAdmins--; - } - - user.Status = IdentityUserStatus.Disabled; - user.LockedUntil = null; - await identityUserRepository.SaveChangesAsync(cancellationToken); - successCount++; - break; - case IdentityUserBatchOperation.Delete: - if (user.Status == IdentityUserStatus.Active - && tenantAdminUserIds.Contains(user.Id) - && remainingActiveAdmins <= 1) - { - throw new BusinessException(ErrorCodes.Conflict, "至少保留一个管理员"); - } - - if (user.Status == IdentityUserStatus.Active && tenantAdminUserIds.Contains(user.Id)) - { - remainingActiveAdmins--; - } - - await identityUserRepository.RemoveAsync(user, cancellationToken); - await identityUserRepository.SaveChangesAsync(cancellationToken); - successCount++; - break; - case IdentityUserBatchOperation.Restore: - if (!user.DeletedAt.HasValue) - { - throw new BusinessException(ErrorCodes.BadRequest, "用户未删除"); - } - - user.DeletedAt = null; - user.DeletedBy = null; - await identityUserRepository.SaveChangesAsync(cancellationToken); - successCount++; - break; - case IdentityUserBatchOperation.Export: - successCount++; - break; - default: - throw new BusinessException(ErrorCodes.BadRequest, "无效的批量操作类型"); - } - } - catch (Exception ex) when (IsConcurrencyException(ex)) - { - failures.Add(new BatchIdentityUserFailureItem - { - UserId = userId, - Reason = "用户数据已被修改,请刷新后重试" - }); - } - catch (BusinessException ex) - { - failures.Add(new BatchIdentityUserFailureItem - { - UserId = userId, - Reason = ex.Message - }); - } - } - // 6.1 处理导出数据 - if (request.Operation == IdentityUserBatchOperation.Export) - { - var roleCodesLookup = await ResolveRoleCodesAsync(users, userRoleRepository, roleRepository, cancellationToken); - var now = DateTime.UtcNow; - exportItems.AddRange(users.Select(user => new UserListItemDto - { - UserId = user.Id, - TenantId = user.TenantId, - Account = user.Account, - DisplayName = user.DisplayName, - Avatar = user.Avatar, - Phone = user.Phone, - Email = user.Email, - Status = user.Status, - IsLocked = user.Status == IdentityUserStatus.Locked || (user.LockedUntil.HasValue && user.LockedUntil.Value > now), - IsDeleted = user.DeletedAt.HasValue, - Roles = roleCodesLookup.TryGetValue(user.Id, out var codes) ? codes : Array.Empty(), - CreatedAt = user.CreatedAt, - LastLoginAt = user.LastLoginAt - })); - } - - // 7. 构建操作日志消息 - var operatorName = string.IsNullOrWhiteSpace(operatorProfile.DisplayName) - ? operatorProfile.Account - : operatorProfile.DisplayName; - if (string.IsNullOrWhiteSpace(operatorName)) - { - operatorName = $"user:{currentUserAccessor.UserId}"; - } - - var logMessage = new IdentityUserOperationLogMessage - { - OperationType = "identity-user:batch", - TargetType = "identity_user", - TargetIds = JsonSerializer.Serialize(userIds), - OperatorId = currentUserAccessor.UserId.ToString(), - OperatorName = operatorName, - Parameters = JsonSerializer.Serialize(new { tenantId, operation = request.Operation.ToString() }), - Result = JsonSerializer.Serialize(new { successCount, failureCount = failures.Count }), - Success = failures.Count == 0 - }; - - // 8. 写入 Outbox 并保存变更 - await operationLogPublisher.PublishAsync(logMessage, cancellationToken); - await identityUserRepository.SaveChangesAsync(cancellationToken); - - return new BatchIdentityUserOperationResult - { - SuccessCount = successCount, - FailureCount = failures.Count, - Failures = failures, - ExportItems = exportItems - }; - } - - private static long[] ParseIds(string[] values, string name) - { - // 1. 空数组直接返回 - if (values.Length == 0) - { - return Array.Empty(); - } - - // 2. 解析并去重 - var ids = new List(values.Length); - foreach (var value in values) - { - if (!long.TryParse(value, out var id) || id <= 0) - { - throw new BusinessException(ErrorCodes.BadRequest, $"{name} ID 无效"); - } - - ids.Add(id); - } - - // 3. 返回去重结果 - return ids.Distinct().ToArray(); - } - - private static async Task> ResolveRoleCodesAsync( - IReadOnlyList users, - IUserRoleRepository userRoleRepository, - IRoleRepository roleRepository, - CancellationToken cancellationToken) - { - // 1. 预分配字典容量 - var result = new Dictionary(users.Count); - - // 2. 按租户分组,降低角色查询次数 - foreach (var group in users.GroupBy(user => user.TenantId)) - { - var tenantId = group.Key; - var userIds = group.Select(user => user.Id).Distinct().ToArray(); - if (userIds.Length == 0) - { - continue; - } - - // 3. 查询用户角色映射 - var relations = await userRoleRepository.GetByUserIdsAsync(tenantId, userIds, cancellationToken); - if (relations.Count == 0) - { - continue; - } - - // 4. 查询角色并构建映射 - var roleIds = relations.Select(x => x.RoleId).Distinct().ToArray(); - var roles = roleIds.Length == 0 - ? Array.Empty() - : await roleRepository.GetByIdsAsync(tenantId, roleIds, cancellationToken); - var roleCodeMap = roles.ToDictionary(role => role.Id, role => role.Code, EqualityComparer.Default); - - // 5. 组装用户角色编码列表 - foreach (var relationGroup in relations.GroupBy(x => x.UserId)) - { - var codes = relationGroup - .Select(x => roleCodeMap.TryGetValue(x.RoleId, out var code) ? code : null) - .OfType() - .Where(code => !string.IsNullOrWhiteSpace(code)) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToArray(); - result[relationGroup.Key] = codes.Length == 0 ? Array.Empty() : codes; - } - } - - return result; - } - - private static bool IsConcurrencyException(Exception exception) - => string.Equals(exception.GetType().Name, "DbUpdateConcurrencyException", StringComparison.Ordinal); -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/BindRolePermissionsCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/BindRolePermissionsCommandHandler.cs deleted file mode 100644 index 4928a72..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/BindRolePermissionsCommandHandler.cs +++ /dev/null @@ -1,53 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Commands; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 绑定角色权限处理器。 -/// -public sealed class BindRolePermissionsCommandHandler( - IRolePermissionRepository rolePermissionRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - /// 处理角色权限绑定请求。 - /// - /// 绑定命令。 - /// 取消标记。 - /// 执行结果。 - public async Task Handle(BindRolePermissionsCommand request, CancellationToken cancellationToken) - { - // 1. 获取租户上下文 - var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (currentTenantId <= 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识"); - } - - // 2. (空行后) 禁止跨租户操作 - if (request.TenantId.HasValue && request.TenantId.Value != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户操作角色权限"); - } - - // 3. (空行后) 覆盖式绑定权限 - var tenantId = currentTenantId; - - var distinctPermissionIds = request.PermissionIds - .Where(id => id > 0) - .Distinct() - .ToArray(); - - await rolePermissionRepository.ReplaceRolePermissionsAsync(tenantId, request.RoleId, distinctPermissionIds, cancellationToken); - await rolePermissionRepository.SaveChangesAsync(cancellationToken); - - // 4. (空行后) 返回执行结果 - return true; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/ChangeIdentityUserStatusCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/ChangeIdentityUserStatusCommandHandler.cs deleted file mode 100644 index 4028bb6..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/ChangeIdentityUserStatusCommandHandler.cs +++ /dev/null @@ -1,146 +0,0 @@ -using MediatR; -using System.Text.Json; -using TakeoutSaaS.Application.Identity.Abstractions; -using TakeoutSaaS.Application.Identity.Commands; -using TakeoutSaaS.Application.Identity.Events; -using TakeoutSaaS.Domain.Identity.Enums; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 更新用户状态处理器。 -/// -public sealed class ChangeIdentityUserStatusCommandHandler( - IIdentityUserRepository identityUserRepository, - IUserRoleRepository userRoleRepository, - IRoleRepository roleRepository, - ITenantProvider tenantProvider, - ICurrentUserAccessor currentUserAccessor, - IAdminAuthService adminAuthService, - IIdentityOperationLogPublisher operationLogPublisher) - : IRequestHandler -{ - /// - public async Task Handle(ChangeIdentityUserStatusCommand request, CancellationToken cancellationToken) - { - // 1. 获取当前租户与操作者档案 - var currentTenantId = tenantProvider.GetCurrentTenantId(); - var operatorProfile = await adminAuthService.GetProfileAsync(currentUserAccessor.UserId, cancellationToken); - - // 2. 校验跨租户访问 - if (request.TenantId.HasValue && request.TenantId.Value != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户修改用户状态"); - } - - // 3. 查询用户实体 - var user = await identityUserRepository.GetForUpdateAsync(request.UserId, cancellationToken); - if (user == null) - { - return false; - } - - if (user.TenantId != currentTenantId) - { - return false; - } - - // 4. 校验租户管理员保留规则 - if (request.Status == IdentityUserStatus.Disabled && user.Status == IdentityUserStatus.Active) - { - await EnsureNotLastActiveTenantAdminAsync(user.TenantId, user.Id, cancellationToken); - } - - // 5. 更新状态 - var previousStatus = user.Status; - switch (request.Status) - { - case IdentityUserStatus.Active: - user.Status = IdentityUserStatus.Active; - user.LockedUntil = null; - user.FailedLoginCount = 0; - break; - case IdentityUserStatus.Disabled: - user.Status = IdentityUserStatus.Disabled; - user.LockedUntil = null; - break; - case IdentityUserStatus.Locked: - user.Status = IdentityUserStatus.Locked; - user.LockedUntil = null; - break; - default: - throw new BusinessException(ErrorCodes.BadRequest, "无效的用户状态"); - } - - // 6. 构建操作日志消息 - var operatorName = string.IsNullOrWhiteSpace(operatorProfile.DisplayName) - ? operatorProfile.Account - : operatorProfile.DisplayName; - if (string.IsNullOrWhiteSpace(operatorName)) - { - operatorName = $"user:{currentUserAccessor.UserId}"; - } - - var logMessage = new IdentityUserOperationLogMessage - { - OperationType = "identity-user:status-change", - TargetType = "identity_user", - TargetIds = JsonSerializer.Serialize(new[] { user.Id }), - OperatorId = currentUserAccessor.UserId.ToString(), - OperatorName = operatorName, - Parameters = JsonSerializer.Serialize(new - { - userId = user.Id, - tenantId = user.TenantId, - previousStatus = previousStatus.ToString(), - currentStatus = user.Status.ToString() - }), - Result = JsonSerializer.Serialize(new { userId = user.Id }), - Success = true - }; - - // 7. 写入 Outbox 并保存变更 - await operationLogPublisher.PublishAsync(logMessage, cancellationToken); - await identityUserRepository.SaveChangesAsync(cancellationToken); - - return true; - } - - private async Task EnsureNotLastActiveTenantAdminAsync(long tenantId, long userId, CancellationToken cancellationToken) - { - // 1. 获取租户管理员角色 - var tenantAdminRole = await roleRepository.FindByCodeAsync("tenant-admin", tenantId, cancellationToken); - if (tenantAdminRole == null) - { - return; - } - - // 2. 判断用户是否为租户管理员 - var relations = await userRoleRepository.GetByUserIdAsync(tenantId, userId, cancellationToken); - if (!relations.Any(x => x.RoleId == tenantAdminRole.Id)) - { - return; - } - - // 3. 统计活跃管理员数量 - var filter = new IdentityUserSearchFilter - { - TenantId = tenantId, - RoleId = tenantAdminRole.Id, - Status = IdentityUserStatus.Active, - IncludeDeleted = false, - Page = 1, - PageSize = 1 - }; - var result = await identityUserRepository.SearchPagedAsync(filter, cancellationToken); - if (result.Total <= 1) - { - throw new BusinessException(ErrorCodes.Conflict, "至少保留一个管理员"); - } - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/CloneRoleTemplateCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/CloneRoleTemplateCommandHandler.cs deleted file mode 100644 index b4bde94..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/CloneRoleTemplateCommandHandler.cs +++ /dev/null @@ -1,73 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Commands; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Domain.Identity.Entities; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 角色模板克隆处理器。 -/// -public sealed class CloneRoleTemplateCommandHandler(IRoleTemplateRepository roleTemplateRepository) - : IRequestHandler -{ - /// - public async Task Handle(CloneRoleTemplateCommand request, CancellationToken cancellationToken) - { - // 1. 校验源模板是否存在 - var source = await roleTemplateRepository.FindByCodeAsync(request.SourceTemplateCode, cancellationToken) - ?? throw new BusinessException(ErrorCodes.NotFound, $"角色模板 {request.SourceTemplateCode} 不存在"); - - // 2. 校验新模板编码是否冲突 - var exists = await roleTemplateRepository.FindByCodeAsync(request.NewTemplateCode, cancellationToken); - if (exists is not null) - { - throw new BusinessException(ErrorCodes.Conflict, $"角色模板编码 {request.NewTemplateCode} 已存在"); - } - - // 3. 获取源模板权限 - var sourcePermissions = await roleTemplateRepository.GetPermissionsAsync(source.Id, cancellationToken); - var permissionCodes = request.PermissionCodes is not null && request.PermissionCodes.Count > 0 - ? request.PermissionCodes.Distinct(StringComparer.OrdinalIgnoreCase).ToArray() - : sourcePermissions - .Select(x => x.PermissionCode) - .Where(code => !string.IsNullOrWhiteSpace(code)) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToArray(); - - // 4. 构造新模板实体 - var target = new RoleTemplate - { - TemplateCode = request.NewTemplateCode.Trim(), - Name = string.IsNullOrWhiteSpace(request.Name) ? source.Name : request.Name.Trim(), - Description = request.Description ?? source.Description, - IsActive = request.IsActive ?? source.IsActive - }; - - // 5. 持久化新模板与权限 - await roleTemplateRepository.AddAsync(target, permissionCodes, cancellationToken); - await roleTemplateRepository.SaveChangesAsync(cancellationToken); - - // 6. 映射返回 DTO - var permissionDtos = permissionCodes - .Select(code => new PermissionTemplateDto - { - Code = code, - Name = code, - Description = code - }) - .ToList(); - - return new RoleTemplateDto - { - TemplateCode = target.TemplateCode, - Name = target.Name, - Description = target.Description, - IsActive = target.IsActive, - Permissions = permissionDtos - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/CopyRoleTemplateCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/CopyRoleTemplateCommandHandler.cs deleted file mode 100644 index cc840af..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/CopyRoleTemplateCommandHandler.cs +++ /dev/null @@ -1,129 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Commands; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Domain.Identity.Entities; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 角色模板复制处理器。 -/// -public sealed class CopyRoleTemplateCommandHandler( - IRoleTemplateRepository roleTemplateRepository, - IRoleRepository roleRepository, - IPermissionRepository permissionRepository, - IRolePermissionRepository rolePermissionRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - public async Task Handle(CopyRoleTemplateCommand request, CancellationToken cancellationToken) - { - // 1. 查询模板与模板权限 - var template = await roleTemplateRepository.FindByCodeAsync(request.TemplateCode, cancellationToken) - ?? throw new BusinessException(ErrorCodes.NotFound, $"角色模板 {request.TemplateCode} 不存在"); - - var templatePermissions = await roleTemplateRepository.GetPermissionsAsync(template.Id, cancellationToken); - var permissionCodes = templatePermissions - .Select(x => x.PermissionCode) - .Where(code => !string.IsNullOrWhiteSpace(code)) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToArray(); - - // 2. 计算角色名称/编码与描述 - var tenantId = tenantProvider.GetCurrentTenantId(); - var roleCode = string.IsNullOrWhiteSpace(request.RoleCode) ? template.TemplateCode : request.RoleCode.Trim(); - var roleName = string.IsNullOrWhiteSpace(request.RoleName) ? template.Name : request.RoleName.Trim(); - var roleDescription = request.Description ?? template.Description; - - // 1. 准备或更新角色主体(幂等创建)。 - var role = await roleRepository.FindByCodeAsync(roleCode, tenantId, cancellationToken); - if (role is null) - { - role = new Role - { - TenantId = tenantId, - Name = roleName, - Code = roleCode, - Description = roleDescription - }; - await roleRepository.AddAsync(role, cancellationToken); - } - else - { - if (!string.IsNullOrWhiteSpace(request.RoleName)) - { - role.Name = roleName; - } - - if (request.Description is not null) - { - role.Description = roleDescription; - } - - await roleRepository.UpdateAsync(role, cancellationToken); - } - - // 3. 确保模板权限全部存在,不存在则按模板定义创建。 - var existingPermissions = await permissionRepository.GetByCodesAsync(tenantId, permissionCodes, cancellationToken); - var permissionMap = existingPermissions.ToDictionary(x => x.Code, StringComparer.OrdinalIgnoreCase); - - foreach (var code in permissionCodes) - { - if (permissionMap.ContainsKey(code)) - { - continue; - } - - var permission = new Permission - { - Name = code, - Code = code, - Description = code - }; - - await permissionRepository.AddAsync(permission, cancellationToken); - permissionMap[code] = permission; - } - - await roleRepository.SaveChangesAsync(cancellationToken); - - // 4. 绑定缺失的权限,保留租户自定义的已有授权。 - var rolePermissions = await rolePermissionRepository.GetByRoleIdsAsync(tenantId, new[] { role.Id }, cancellationToken); - var existingPermissionIds = rolePermissions - .Select(x => x.PermissionId) - .ToHashSet(); - - var targetPermissionIds = permissionCodes - .Select(code => permissionMap[code].Id) - .ToHashSet(); - - var toAdd = targetPermissionIds.Except(existingPermissionIds).ToArray(); - if (toAdd.Length > 0) - { - var relations = toAdd.Select(permissionId => new RolePermission - { - TenantId = tenantId, - RoleId = role.Id, - PermissionId = permissionId - }); - - await rolePermissionRepository.AddRangeAsync(relations, cancellationToken); - } - - await rolePermissionRepository.SaveChangesAsync(cancellationToken); - - return new RoleDto - { - Id = role.Id, - TenantId = role.TenantId, - Name = role.Name, - Code = role.Code, - Description = role.Description - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/CreateIdentityUserCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/CreateIdentityUserCommandHandler.cs deleted file mode 100644 index b031905..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/CreateIdentityUserCommandHandler.cs +++ /dev/null @@ -1,190 +0,0 @@ -using MediatR; -using Microsoft.AspNetCore.Identity; -using System.Text.Json; -using TakeoutSaaS.Application.Identity.Abstractions; -using TakeoutSaaS.Application.Identity.Commands; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Application.Identity.Events; -using TakeoutSaaS.Application.Identity.Queries; -using TakeoutSaaS.Domain.Identity.Entities; -using TakeoutSaaS.Domain.Identity.Enums; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Ids; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 创建用户处理器。 -/// -public sealed class CreateIdentityUserCommandHandler( - IIdentityUserRepository identityUserRepository, - IUserRoleRepository userRoleRepository, - IRoleRepository roleRepository, - IPasswordHasher passwordHasher, - ITenantProvider tenantProvider, - ICurrentUserAccessor currentUserAccessor, - IAdminAuthService adminAuthService, - IIdentityOperationLogPublisher operationLogPublisher, - IIdGenerator idGenerator, - IMediator mediator) - : IRequestHandler -{ - /// - public async Task Handle(CreateIdentityUserCommand request, CancellationToken cancellationToken) - { - // 1. 获取当前租户与操作者档案 - var currentTenantId = tenantProvider.GetCurrentTenantId(); - var operatorProfile = await adminAuthService.GetProfileAsync(currentUserAccessor.UserId, cancellationToken); - - // 2. 校验跨租户访问 - if (request.TenantId.HasValue && request.TenantId.Value != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户创建用户"); - } - - // 3. 规范化输入并准备校验 - var tenantId = currentTenantId; - var account = request.Account.Trim(); - var displayName = request.DisplayName.Trim(); - var phone = string.IsNullOrWhiteSpace(request.Phone) ? null : request.Phone.Trim(); - var email = string.IsNullOrWhiteSpace(request.Email) ? null : request.Email.Trim(); - var roleIds = ParseIds(request.RoleIds, "角色"); - - // 4. 唯一性校验 - if (await identityUserRepository.ExistsByAccountAsync(tenantId, account, null, cancellationToken)) - { - throw new BusinessException(ErrorCodes.Conflict, "账号已存在"); - } - - if (!string.IsNullOrWhiteSpace(phone) - && await identityUserRepository.ExistsByPhoneAsync(tenantId, phone, null, cancellationToken)) - { - throw new BusinessException(ErrorCodes.Conflict, "手机号已存在"); - } - - if (!string.IsNullOrWhiteSpace(email) - && await identityUserRepository.ExistsByEmailAsync(tenantId, email, null, cancellationToken)) - { - throw new BusinessException(ErrorCodes.Conflict, "邮箱已存在"); - } - - // 5. 校验角色合法性 - if (roleIds.Length > 0) - { - var roles = await roleRepository.GetByIdsAsync(tenantId, roleIds, cancellationToken); - if (roles.Count != roleIds.Length) - { - throw new BusinessException(ErrorCodes.BadRequest, "角色列表包含无效项"); - } - } - - // 6. 创建用户实体 - var user = new IdentityUser - { - Id = idGenerator.NextId(), - TenantId = tenantId, - Account = account, - DisplayName = displayName, - Phone = phone, - Email = email, - Avatar = string.IsNullOrWhiteSpace(request.Avatar) ? null : request.Avatar.Trim(), - Status = request.Status ?? IdentityUserStatus.Active, - FailedLoginCount = 0, - LockedUntil = null, - LastLoginAt = null, - MustChangePassword = false, - PasswordHash = string.Empty - }; - user.PasswordHash = passwordHasher.HashPassword(user, request.Password); - - // 7. 构建操作日志消息 - var operatorName = string.IsNullOrWhiteSpace(operatorProfile.DisplayName) - ? operatorProfile.Account - : operatorProfile.DisplayName; - if (string.IsNullOrWhiteSpace(operatorName)) - { - operatorName = $"user:{currentUserAccessor.UserId}"; - } - - var logMessage = new IdentityUserOperationLogMessage - { - OperationType = "identity-user:create", - TargetType = "identity_user", - TargetIds = JsonSerializer.Serialize(new[] { user.Id }), - OperatorId = currentUserAccessor.UserId.ToString(), - OperatorName = operatorName, - Parameters = JsonSerializer.Serialize(new - { - tenantId, - account, - displayName, - phone, - email, - roleIds - }), - Result = JsonSerializer.Serialize(new { userId = user.Id }), - Success = true - }; - - // 8. 持久化用户并写入 Outbox - await identityUserRepository.AddAsync(user, cancellationToken); - await operationLogPublisher.PublishAsync(logMessage, cancellationToken); - await identityUserRepository.SaveChangesAsync(cancellationToken); - - // 9. 绑定角色 - if (roleIds.Length > 0) - { - await userRoleRepository.ReplaceUserRolesAsync(tenantId, user.Id, roleIds, cancellationToken); - } - - // 10. 返回用户详情 - var detail = await mediator.Send(new GetIdentityUserDetailQuery { UserId = user.Id }, cancellationToken); - return detail ?? new UserDetailDto - { - UserId = user.Id, - TenantId = user.TenantId, - MerchantId = user.MerchantId, - Account = user.Account, - DisplayName = user.DisplayName, - Phone = user.Phone, - Email = user.Email, - Status = user.Status, - IsLocked = false, - Roles = Array.Empty(), - RoleIds = Array.Empty(), - Permissions = Array.Empty(), - CreatedAt = user.CreatedAt, - LastLoginAt = user.LastLoginAt, - Avatar = user.Avatar, - RowVersion = user.RowVersion - }; - } - - private static long[] ParseIds(string[] values, string name) - { - // 1. 空数组直接返回 - if (values.Length == 0) - { - return Array.Empty(); - } - - // 2. 解析并去重 - var ids = new List(values.Length); - foreach (var value in values) - { - if (!long.TryParse(value, out var id) || id <= 0) - { - throw new BusinessException(ErrorCodes.BadRequest, $"{name} ID 无效"); - } - - ids.Add(id); - } - - // 3. 返回去重结果 - return ids.Distinct().ToArray(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/CreateMenuCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/CreateMenuCommandHandler.cs deleted file mode 100644 index 9ae4bc3..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/CreateMenuCommandHandler.cs +++ /dev/null @@ -1,57 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Commands; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Application.Identity; -using TakeoutSaaS.Domain.Identity.Entities; -using TakeoutSaaS.Domain.Identity.Enums; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 创建菜单处理器。 -/// -public sealed class CreateMenuCommandHandler(IMenuRepository menuRepository) - : IRequestHandler -{ - /// - public async Task Handle(CreateMenuCommand request, CancellationToken cancellationToken) - { - // 1. 菜单固定时禁止新增 - if (!MenuPolicy.CanMaintainMenus) - { - throw new BusinessException(ErrorCodes.Forbidden, "菜单已固定,禁止新增"); - } - - // 2. 构造实体 - var entity = new MenuDefinition - { - Portal = PortalType.Tenant, - ParentId = request.ParentId, - Name = request.Name.Trim(), - Path = request.Path.Trim(), - Component = request.Component.Trim(), - Title = request.Title.Trim(), - Icon = request.Icon?.Trim(), - IsIframe = request.IsIframe, - Link = string.IsNullOrWhiteSpace(request.Link) ? null : request.Link.Trim(), - KeepAlive = request.KeepAlive, - SortOrder = request.SortOrder, - RequiredPermissions = MenuMapper.JoinCodes(request.RequiredPermissions), - MetaPermissions = MenuMapper.JoinCodes(request.MetaPermissions), - MetaRoles = MenuMapper.JoinCodes(request.MetaRoles), - AuthListJson = request.AuthList.Count == 0 - ? null - : System.Text.Json.JsonSerializer.Serialize(request.AuthList) - }; - - // 3. 持久化 - await menuRepository.AddAsync(entity, cancellationToken); - await menuRepository.SaveChangesAsync(cancellationToken); - - // 4. 返回 DTO - return MenuMapper.ToDto(entity); - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/CreatePermissionCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/CreatePermissionCommandHandler.cs deleted file mode 100644 index cc7cfee..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/CreatePermissionCommandHandler.cs +++ /dev/null @@ -1,70 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Commands; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Domain.Identity.Entities; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 创建权限处理器。 -/// -public sealed class CreatePermissionCommandHandler( - IPermissionRepository permissionRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - /// 处理创建权限请求。 - /// - /// 创建命令。 - /// 取消标记。 - /// 创建后的权限 DTO。 - public async Task Handle(CreatePermissionCommand request, CancellationToken cancellationToken) - { - // 1. 权限固定时禁止新增 - if (!PermissionPolicy.CanMaintainPermissions) - { - throw new BusinessException(ErrorCodes.Forbidden, "权限已固定,禁止新增"); - } - - // 2. 获取租户上下文 - var tenantId = tenantProvider.GetCurrentTenantId(); - - // 3. 构建权限实体 - var normalizedType = string.IsNullOrWhiteSpace(request.Type) - ? "leaf" - : request.Type.Trim().ToLowerInvariant(); - normalizedType = normalizedType is "group" or "leaf" ? normalizedType : "leaf"; - var parentId = request.ParentId > 0 ? request.ParentId : 0; - var sortOrder = request.SortOrder < 0 ? 0 : request.SortOrder; - var permission = new Permission - { - ParentId = parentId, - SortOrder = sortOrder, - Type = normalizedType, - Name = request.Name, - Code = request.Code, - Description = request.Description - }; - - // 4. 持久化 - await permissionRepository.AddAsync(permission, cancellationToken); - await permissionRepository.SaveChangesAsync(cancellationToken); - - // 5. 返回 DTO - return new PermissionDto - { - Id = permission.Id, - ParentId = permission.ParentId, - SortOrder = permission.SortOrder, - Type = permission.Type, - Name = permission.Name, - Code = permission.Code, - Description = permission.Description - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/CreateRoleCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/CreateRoleCommandHandler.cs deleted file mode 100644 index 1008782..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/CreateRoleCommandHandler.cs +++ /dev/null @@ -1,81 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Commands; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Domain.Identity.Entities; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 创建角色处理器。 -/// -public sealed class CreateRoleCommandHandler( - IRoleRepository roleRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - /// 处理创建角色请求。 - /// - /// 创建命令。 - /// 取消标记。 - /// 创建后的角色 DTO。 - public async Task Handle(CreateRoleCommand request, CancellationToken cancellationToken) - { - // 1. 获取租户上下文并校验跨租户 - var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (currentTenantId <= 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识"); - } - - // 2. (空行后) 禁止跨租户创建 - if (request.TenantId.HasValue && request.TenantId.Value != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户创建角色"); - } - - // 3. (空行后) 使用当前租户创建角色 - var tenantId = currentTenantId; - - // 4. (空行后) 归一化输入并校验唯一 - var name = request.Name?.Trim() ?? string.Empty; - var code = request.Code?.Trim() ?? string.Empty; - if (string.IsNullOrWhiteSpace(name) || string.IsNullOrWhiteSpace(code)) - { - throw new BusinessException(ErrorCodes.BadRequest, "角色名称与编码不能为空"); - } - - var exists = await roleRepository.FindByCodeAsync(code, tenantId, cancellationToken); - if (exists is not null) - { - throw new BusinessException(ErrorCodes.Conflict, "角色编码已存在"); - } - - // 5. (空行后) 构建角色实体 - var role = new Role - { - TenantId = tenantId, - Name = name, - Code = code, - Description = request.Description - }; - - // 6. (空行后) 持久化 - await roleRepository.AddAsync(role, cancellationToken); - await roleRepository.SaveChangesAsync(cancellationToken); - - // 7. (空行后) 返回 DTO - return new RoleDto - { - Id = role.Id, - TenantId = role.TenantId, - Name = role.Name, - Code = role.Code, - Description = role.Description - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/CreateRoleTemplateCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/CreateRoleTemplateCommandHandler.cs deleted file mode 100644 index 2bec7ea..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/CreateRoleTemplateCommandHandler.cs +++ /dev/null @@ -1,55 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Commands; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Domain.Identity.Entities; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 创建角色模板处理器。 -/// -public sealed class CreateRoleTemplateCommandHandler(IRoleTemplateRepository roleTemplateRepository) - : IRequestHandler -{ - /// - public async Task Handle(CreateRoleTemplateCommand request, CancellationToken cancellationToken) - { - // 1. 校验必填 - if (string.IsNullOrWhiteSpace(request.TemplateCode) || string.IsNullOrWhiteSpace(request.Name)) - { - throw new BusinessException(ErrorCodes.BadRequest, "模板编码与名称不能为空"); - } - - // 2. 检查编码唯一 - var existing = await roleTemplateRepository.FindByCodeAsync(request.TemplateCode, cancellationToken); - if (existing != null) - { - throw new BusinessException(ErrorCodes.Conflict, $"模板编码 {request.TemplateCode} 已存在"); - } - - // 3. 构建模板实体 - var template = new RoleTemplate - { - TemplateCode = request.TemplateCode.Trim(), - Name = request.Name.Trim(), - Description = request.Description, - IsActive = request.IsActive - }; - - // 4. 清洗权限编码 - var permissions = request.PermissionCodes - .Where(code => !string.IsNullOrWhiteSpace(code)) - .Select(code => code.Trim()) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToArray(); - - // 5. 持久化并返回 DTO - await roleTemplateRepository.AddAsync(template, permissions, cancellationToken); - await roleTemplateRepository.SaveChangesAsync(cancellationToken); - - return TemplateMapper.ToDto(template, permissions); - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteIdentityUserCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteIdentityUserCommandHandler.cs deleted file mode 100644 index 644ecee..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteIdentityUserCommandHandler.cs +++ /dev/null @@ -1,120 +0,0 @@ -using MediatR; -using System.Text.Json; -using TakeoutSaaS.Application.Identity.Abstractions; -using TakeoutSaaS.Application.Identity.Commands; -using TakeoutSaaS.Application.Identity.Events; -using TakeoutSaaS.Domain.Identity.Enums; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 删除用户处理器。 -/// -public sealed class DeleteIdentityUserCommandHandler( - IIdentityUserRepository identityUserRepository, - IUserRoleRepository userRoleRepository, - IRoleRepository roleRepository, - ITenantProvider tenantProvider, - ICurrentUserAccessor currentUserAccessor, - IAdminAuthService adminAuthService, - IIdentityOperationLogPublisher operationLogPublisher) - : IRequestHandler -{ - /// - public async Task Handle(DeleteIdentityUserCommand request, CancellationToken cancellationToken) - { - // 1. 获取当前租户与操作者档案 - var currentTenantId = tenantProvider.GetCurrentTenantId(); - var operatorProfile = await adminAuthService.GetProfileAsync(currentUserAccessor.UserId, cancellationToken); - - // 2. 校验跨租户访问 - if (request.TenantId.HasValue && request.TenantId.Value != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户删除用户"); - } - - // 3. 查询用户实体 - var user = await identityUserRepository.GetForUpdateAsync(request.UserId, cancellationToken); - if (user == null) - { - return false; - } - - if (user.TenantId != currentTenantId) - { - return false; - } - - // 4. 校验租户管理员保留规则 - if (user.Status == IdentityUserStatus.Active) - { - await EnsureNotLastActiveTenantAdminAsync(user.TenantId, user.Id, cancellationToken); - } - - // 5. 构建操作日志消息 - var operatorName = string.IsNullOrWhiteSpace(operatorProfile.DisplayName) - ? operatorProfile.Account - : operatorProfile.DisplayName; - if (string.IsNullOrWhiteSpace(operatorName)) - { - operatorName = $"user:{currentUserAccessor.UserId}"; - } - - var logMessage = new IdentityUserOperationLogMessage - { - OperationType = "identity-user:delete", - TargetType = "identity_user", - TargetIds = JsonSerializer.Serialize(new[] { user.Id }), - OperatorId = currentUserAccessor.UserId.ToString(), - OperatorName = operatorName, - Parameters = JsonSerializer.Serialize(new { userId = user.Id, tenantId = user.TenantId }), - Result = JsonSerializer.Serialize(new { userId = user.Id }), - Success = true - }; - - // 6. 软删除用户并写入 Outbox - await identityUserRepository.RemoveAsync(user, cancellationToken); - await operationLogPublisher.PublishAsync(logMessage, cancellationToken); - await identityUserRepository.SaveChangesAsync(cancellationToken); - - return true; - } - - private async Task EnsureNotLastActiveTenantAdminAsync(long tenantId, long userId, CancellationToken cancellationToken) - { - // 1. 获取租户管理员角色 - var tenantAdminRole = await roleRepository.FindByCodeAsync("tenant-admin", tenantId, cancellationToken); - if (tenantAdminRole == null) - { - return; - } - - // 2. 判断用户是否为租户管理员 - var relations = await userRoleRepository.GetByUserIdAsync(tenantId, userId, cancellationToken); - if (!relations.Any(x => x.RoleId == tenantAdminRole.Id)) - { - return; - } - - // 3. 统计活跃管理员数量 - var filter = new IdentityUserSearchFilter - { - TenantId = tenantId, - RoleId = tenantAdminRole.Id, - Status = IdentityUserStatus.Active, - IncludeDeleted = false, - Page = 1, - PageSize = 1 - }; - var result = await identityUserRepository.SearchPagedAsync(filter, cancellationToken); - if (result.Total <= 1) - { - throw new BusinessException(ErrorCodes.Conflict, "至少保留一个管理员"); - } - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteMenuCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteMenuCommandHandler.cs deleted file mode 100644 index 545729f..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteMenuCommandHandler.cs +++ /dev/null @@ -1,34 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity; -using TakeoutSaaS.Application.Identity.Commands; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 删除菜单处理器。 -/// -public sealed class DeleteMenuCommandHandler(IMenuRepository menuRepository) - : IRequestHandler -{ - /// - public async Task Handle(DeleteMenuCommand request, CancellationToken cancellationToken) - { - // 1. 菜单固定时禁止删除 - if (!MenuPolicy.CanMaintainMenus) - { - throw new BusinessException(ErrorCodes.Forbidden, "菜单已固定,禁止删除"); - } - - // 2. 删除目标 - await menuRepository.DeleteAsync(request.Id, cancellationToken); - - // 3. 持久化 - await menuRepository.SaveChangesAsync(cancellationToken); - - // 4. 返回执行结果 - return true; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/DeletePermissionCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/DeletePermissionCommandHandler.cs deleted file mode 100644 index fb31f03..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/DeletePermissionCommandHandler.cs +++ /dev/null @@ -1,42 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Commands; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 删除权限处理器。 -/// -public sealed class DeletePermissionCommandHandler( - IPermissionRepository permissionRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - /// 处理删除权限请求。 - /// - /// 删除命令。 - /// 取消标记。 - /// 执行结果。 - public async Task Handle(DeletePermissionCommand request, CancellationToken cancellationToken) - { - // 1. 权限固定时禁止删除 - if (!PermissionPolicy.CanMaintainPermissions) - { - throw new BusinessException(ErrorCodes.Forbidden, "权限已固定,禁止删除"); - } - - // 2. 获取租户上下文 - var tenantId = tenantProvider.GetCurrentTenantId(); - - // 3. 删除权限 - await permissionRepository.DeleteAsync(request.PermissionId, tenantId, cancellationToken); - await permissionRepository.SaveChangesAsync(cancellationToken); - - // 4. 返回执行结果 - return true; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteRoleCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteRoleCommandHandler.cs deleted file mode 100644 index 592df9a..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteRoleCommandHandler.cs +++ /dev/null @@ -1,48 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Commands; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 删除角色处理器。 -/// -public sealed class DeleteRoleCommandHandler( - IRoleRepository roleRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - /// 处理删除角色请求。 - /// - /// 删除命令。 - /// 取消标记。 - /// 执行结果。 - public async Task Handle(DeleteRoleCommand request, CancellationToken cancellationToken) - { - // 1. 获取租户上下文 - var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (currentTenantId <= 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识"); - } - - // 2. (空行后) 禁止跨租户操作 - if (request.TenantId.HasValue && request.TenantId.Value != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户操作角色"); - } - - // 3. (空行后) 删除角色 - var tenantId = currentTenantId; - - await roleRepository.DeleteAsync(request.RoleId, tenantId, cancellationToken); - await roleRepository.SaveChangesAsync(cancellationToken); - - // 4. (空行后) 返回执行结果 - return true; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteRoleTemplateCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteRoleTemplateCommandHandler.cs deleted file mode 100644 index c021564..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteRoleTemplateCommandHandler.cs +++ /dev/null @@ -1,35 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Commands; -using TakeoutSaaS.Domain.Identity.Repositories; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 删除角色模板处理器。 -/// -public sealed class DeleteRoleTemplateCommandHandler(IRoleTemplateRepository roleTemplateRepository) - : IRequestHandler -{ - /// - /// 处理删除角色模板请求。 - /// - /// 删除命令。 - /// 取消标记。 - /// 执行结果。 - public async Task Handle(DeleteRoleTemplateCommand request, CancellationToken cancellationToken) - { - // 1. 查询模板 - var template = await roleTemplateRepository.FindByCodeAsync(request.TemplateCode, cancellationToken); - if (template == null) - { - return false; - } - - // 2. 删除并保存 - await roleTemplateRepository.DeleteAsync(template.Id, cancellationToken); - await roleTemplateRepository.SaveChangesAsync(cancellationToken); - - // 3. 返回执行结果 - return true; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/GetIdentityUserDetailQueryHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/GetIdentityUserDetailQueryHandler.cs deleted file mode 100644 index 07ec79f..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/GetIdentityUserDetailQueryHandler.cs +++ /dev/null @@ -1,96 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Application.Identity.Queries; -using TakeoutSaaS.Domain.Identity.Entities; -using TakeoutSaaS.Domain.Identity.Enums; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 获取用户详情处理器。 -/// -public sealed class GetIdentityUserDetailQueryHandler( - IIdentityUserRepository identityUserRepository, - IUserRoleRepository userRoleRepository, - IRoleRepository roleRepository, - IRolePermissionRepository rolePermissionRepository, - IPermissionRepository permissionRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - public async Task Handle(GetIdentityUserDetailQuery request, CancellationToken cancellationToken) - { - // 1. 获取当前租户 - var currentTenantId = tenantProvider.GetCurrentTenantId(); - - // 2. 查询用户实体 - IdentityUser? user; - if (request.IncludeDeleted) - { - user = await identityUserRepository.GetForUpdateIncludingDeletedAsync(currentTenantId, request.UserId, cancellationToken); - } - else - { - user = await identityUserRepository.GetForUpdateAsync(request.UserId, cancellationToken); - } - - if (user == null) - { - return null; - } - - if (user.TenantId != currentTenantId) - { - return null; - } - - // 3. 加载角色与权限 - var roleRelations = await userRoleRepository.GetByUserIdAsync(user.TenantId, user.Id, cancellationToken); - var roleIds = roleRelations.Select(x => x.RoleId).Distinct().ToArray(); - var roles = roleIds.Length == 0 - ? Array.Empty() - : await roleRepository.GetByIdsAsync(user.TenantId, roleIds, cancellationToken); - var roleCodes = roles.Select(x => x.Code) - .Where(code => !string.IsNullOrWhiteSpace(code)) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToArray(); - var permissionIds = roleIds.Length == 0 - ? Array.Empty() - : (await rolePermissionRepository.GetByRoleIdsAsync(user.TenantId, roleIds, cancellationToken)) - .Select(x => x.PermissionId) - .Distinct() - .ToArray(); - var permissions = permissionIds.Length == 0 - ? Array.Empty() - : (await permissionRepository.GetByIdsAsync(user.TenantId, permissionIds, cancellationToken)) - .Select(x => x.Code) - .Where(code => !string.IsNullOrWhiteSpace(code)) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToArray(); - - // 4. 组装详情 DTO - var now = DateTime.UtcNow; - return new UserDetailDto - { - UserId = user.Id, - TenantId = user.TenantId, - MerchantId = user.MerchantId, - Account = user.Account, - DisplayName = user.DisplayName, - Phone = user.Phone, - Email = user.Email, - Status = user.Status, - IsLocked = user.Status == IdentityUserStatus.Locked || (user.LockedUntil.HasValue && user.LockedUntil.Value > now), - Roles = roleCodes, - RoleIds = roleIds.Select(id => id.ToString()).ToArray(), - Permissions = permissions, - CreatedAt = user.CreatedAt, - LastLoginAt = user.LastLoginAt, - Avatar = user.Avatar, - RowVersion = user.RowVersion - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/GetRoleTemplateQueryHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/GetRoleTemplateQueryHandler.cs deleted file mode 100644 index be16a6e..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/GetRoleTemplateQueryHandler.cs +++ /dev/null @@ -1,31 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Application.Identity.Queries; -using TakeoutSaaS.Domain.Identity.Repositories; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 角色模板详情查询处理器。 -/// -public sealed class GetRoleTemplateQueryHandler(IRoleTemplateRepository roleTemplateRepository) - : IRequestHandler -{ - /// - public async Task Handle(GetRoleTemplateQuery request, CancellationToken cancellationToken) - { - // 1. 查询模板 - var template = await roleTemplateRepository.FindByCodeAsync(request.TemplateCode, cancellationToken); - if (template == null) - { - return null; - } - - // 2. 查询模板权限 - var permissions = await roleTemplateRepository.GetPermissionsAsync(template.Id, cancellationToken); - var codes = permissions.Select(x => x.PermissionCode).ToArray(); - - // 3. 返回 DTO - return TemplateMapper.ToDto(template, codes); - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/GetUserPermissionsQueryHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/GetUserPermissionsQueryHandler.cs deleted file mode 100644 index 915f386..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/GetUserPermissionsQueryHandler.cs +++ /dev/null @@ -1,87 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Application.Identity.Queries; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 按用户 ID 获取权限概览处理器。 -/// -public sealed class GetUserPermissionsQueryHandler( - IIdentityUserRepository identityUserRepository, - IUserRoleRepository userRoleRepository, - IRoleRepository roleRepository, - IPermissionRepository permissionRepository, - IRolePermissionRepository rolePermissionRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - public async Task Handle(GetUserPermissionsQuery request, CancellationToken cancellationToken) - { - // 1. 获取租户并查询用户 - var tenantId = tenantProvider.GetCurrentTenantId(); - var user = await identityUserRepository.FindByIdAsync(request.UserId, cancellationToken); - if (user == null || user.TenantId != tenantId) - { - return null; - } - - // 2. 解析角色与权限 - var roleCodes = await ResolveUserRolesAsync(tenantId, user.Id, cancellationToken); - var permissionCodes = await ResolveUserPermissionsAsync(tenantId, user.Id, cancellationToken); - - // 3. 返回用户权限概览 - return new UserPermissionDto - { - UserId = user.Id, - TenantId = user.TenantId, - MerchantId = user.MerchantId, - Account = user.Account, - DisplayName = user.DisplayName, - Roles = roleCodes, - Permissions = permissionCodes, - CreatedAt = user.CreatedAt - }; - } - - private async Task ResolveUserRolesAsync(long tenantId, long userId, CancellationToken cancellationToken) - { - // 1. 查询用户角色关系 - var relations = await userRoleRepository.GetByUserIdAsync(tenantId, userId, cancellationToken); - var roleIds = relations.Select(x => x.RoleId).Distinct().ToArray(); - if (roleIds.Length == 0) - { - return Array.Empty(); - } - - // 2. 查询角色编码 - var roles = await roleRepository.GetByIdsAsync(tenantId, roleIds, cancellationToken); - return roles.Select(x => x.Code).Distinct(StringComparer.OrdinalIgnoreCase).ToArray(); - } - - private async Task ResolveUserPermissionsAsync(long tenantId, long userId, CancellationToken cancellationToken) - { - // 1. 查询用户角色关系 - var relations = await userRoleRepository.GetByUserIdAsync(tenantId, userId, cancellationToken); - var roleIds = relations.Select(x => x.RoleId).Distinct().ToArray(); - if (roleIds.Length == 0) - { - return Array.Empty(); - } - - // 2. 查询角色-权限关系 - var rolePermissions = await rolePermissionRepository.GetByRoleIdsAsync(tenantId, roleIds, cancellationToken); - var permissionIds = rolePermissions.Select(x => x.PermissionId).Distinct().ToArray(); - if (permissionIds.Length == 0) - { - return Array.Empty(); - } - - // 3. 查询权限编码 - var permissions = await permissionRepository.GetByIdsAsync(tenantId, permissionIds, cancellationToken); - return permissions.Select(x => x.Code).Distinct(StringComparer.OrdinalIgnoreCase).ToArray(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/InitializeRoleTemplatesCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/InitializeRoleTemplatesCommandHandler.cs deleted file mode 100644 index 7ec7a0e..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/InitializeRoleTemplatesCommandHandler.cs +++ /dev/null @@ -1,62 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Commands; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 租户角色模板批量初始化处理器。 -/// -public sealed class InitializeRoleTemplatesCommandHandler( - IRoleTemplateRepository roleTemplateRepository, - IMediator mediator) - : IRequestHandler> -{ - /// - public async Task> Handle(InitializeRoleTemplatesCommand request, CancellationToken cancellationToken) - { - // 1. 解析需要初始化的模板编码,默认取全部模板。 - var requestedCodes = request.TemplateCodes? - .Where(code => !string.IsNullOrWhiteSpace(code)) - .Select(code => code.Trim()) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToArray(); - - var availableTemplates = await roleTemplateRepository.GetAllAsync(true, cancellationToken); - var availableCodes = availableTemplates.Select(t => t.TemplateCode).ToHashSet(StringComparer.OrdinalIgnoreCase); - - var targetCodes = requestedCodes?.Length > 0 - ? requestedCodes - : availableTemplates.Select(template => template.TemplateCode).ToArray(); - - if (targetCodes.Length == 0) - { - return Array.Empty(); - } - - foreach (var code in targetCodes) - { - if (!availableCodes.Contains(code)) - { - throw new BusinessException(ErrorCodes.NotFound, $"角色模板 {code} 不存在或未启用"); - } - } - - // 2. 逐个复制模板,幂等写入角色与权限。 - var roles = new List(targetCodes.Length); - foreach (var templateCode in targetCodes) - { - var role = await mediator.Send(new CopyRoleTemplateCommand - { - TemplateCode = templateCode - }, cancellationToken); - - roles.Add(role); - } - - return roles; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/ListMenusQueryHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/ListMenusQueryHandler.cs deleted file mode 100644 index c224928..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/ListMenusQueryHandler.cs +++ /dev/null @@ -1,27 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Application.Identity.Queries; -using TakeoutSaaS.Domain.Identity.Enums; -using TakeoutSaaS.Domain.Identity.Repositories; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 菜单列表查询处理器。 -/// -public sealed class ListMenusQueryHandler(IMenuRepository menuRepository) - : IRequestHandler> -{ - /// - public async Task> Handle(ListMenusQuery request, CancellationToken cancellationToken) - { - // 1. 查询租户端菜单 - var entities = await menuRepository.GetByPortalAsync(PortalType.Tenant, cancellationToken); - - // 2. 映射 DTO - var items = entities.Select(MenuMapper.ToDto).ToList(); - - // 3. 返回结果 - return items; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/ListRoleTemplatesQueryHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/ListRoleTemplatesQueryHandler.cs deleted file mode 100644 index e99254b..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/ListRoleTemplatesQueryHandler.cs +++ /dev/null @@ -1,36 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Application.Identity.Queries; -using TakeoutSaaS.Domain.Identity.Repositories; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 角色模板列表查询处理器。 -/// -public sealed class ListRoleTemplatesQueryHandler(IRoleTemplateRepository roleTemplateRepository) - : IRequestHandler> -{ - /// - public async Task> Handle(ListRoleTemplatesQuery request, CancellationToken cancellationToken) - { - // 1. 查询模板与权限映射 - var templates = await roleTemplateRepository.GetAllAsync(request.IsActive, cancellationToken); - var permissionsMap = await roleTemplateRepository.GetPermissionsAsync(templates.Select(t => t.Id), cancellationToken); - - // 2. 排序并映射 DTO - var dtos = templates - .OrderBy(template => template.TemplateCode, StringComparer.OrdinalIgnoreCase) - .Select(template => - { - var codes = permissionsMap.TryGetValue(template.Id, out var perms) - ? (IReadOnlyCollection)perms.Select(p => p.PermissionCode).ToArray() - : Array.Empty(); - return TemplateMapper.ToDto(template, codes); - }) - .ToArray(); - - // 3. 返回结果 - return dtos; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/MenuDetailQueryHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/MenuDetailQueryHandler.cs deleted file mode 100644 index 5e89430..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/MenuDetailQueryHandler.cs +++ /dev/null @@ -1,27 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Application.Identity.Queries; -using TakeoutSaaS.Domain.Identity.Repositories; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 菜单详情查询处理器。 -/// -public sealed class MenuDetailQueryHandler(IMenuRepository menuRepository) - : IRequestHandler -{ - /// - public async Task Handle(MenuDetailQuery request, CancellationToken cancellationToken) - { - // 1. 查询实体 - var entity = await menuRepository.FindByIdAsync(request.Id, cancellationToken); - if (entity is null) - { - return null; - } - - // 2. 映射并返回 - return MenuMapper.ToDto(entity); - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/MenuMapper.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/MenuMapper.cs deleted file mode 100644 index 22c39f3..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/MenuMapper.cs +++ /dev/null @@ -1,129 +0,0 @@ -using System.Text.Json; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Domain.Identity.Entities; -using TakeoutSaaS.Domain.Identity.Enums; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 菜单映射辅助。 -/// -internal static class MenuMapper -{ - /// - /// 将菜单实体映射为 DTO。 - /// - /// 菜单实体。 - /// 菜单定义 DTO。 - public static MenuDefinitionDto ToDto(MenuDefinition entity) - { - // 1. 解析权限字段 - var requiredPermissions = SplitCodes(entity.RequiredPermissions); - var metaPermissions = SplitCodes(entity.MetaPermissions); - var metaRoles = SplitCodes(entity.MetaRoles); - - // 2. 解析按钮权限 - var authList = string.IsNullOrWhiteSpace(entity.AuthListJson) - ? [] - : JsonSerializer.Deserialize>(entity.AuthListJson) ?? []; - - // 3. 输出 DTO - return new MenuDefinitionDto - { - Id = entity.Id, - ParentId = entity.ParentId, - Name = entity.Name, - Path = entity.Path, - Component = entity.Component, - Title = entity.Title, - Icon = entity.Icon, - IsIframe = entity.IsIframe, - Link = entity.Link, - KeepAlive = entity.KeepAlive, - SortOrder = entity.SortOrder, - RequiredPermissions = requiredPermissions, - MetaPermissions = metaPermissions, - MetaRoles = metaRoles, - AuthList = authList - }; - } - - /// - /// 将 DTO 字段填充到实体。 - /// - /// 菜单实体。 - /// 菜单 DTO。 - public static void FillEntity(MenuDefinition entity, MenuDefinitionDto dto) - { - // 1. 赋值基础字段 - entity.ParentId = dto.ParentId; - entity.Name = dto.Name; - entity.Path = dto.Path; - entity.Component = dto.Component; - entity.Title = dto.Title; - entity.Icon = dto.Icon; - entity.IsIframe = dto.IsIframe; - entity.Link = dto.Link; - entity.KeepAlive = dto.KeepAlive; - entity.SortOrder = dto.SortOrder; - - // 2. 权限与按钮 - entity.RequiredPermissions = JoinCodes(dto.RequiredPermissions); - entity.MetaPermissions = JoinCodes(dto.MetaPermissions); - entity.MetaRoles = JoinCodes(dto.MetaRoles); - entity.AuthListJson = dto.AuthList.Count == 0 - ? null - : JsonSerializer.Serialize(dto.AuthList); - } - - /// - /// 构建或更新菜单实体并返回 DTO。 - /// - /// 已存在的菜单实体。 - /// 门户类型。 - /// 菜单 DTO 载荷。 - /// 菜单定义 DTO。 - public static MenuDefinitionDto FromCommand(MenuDefinition? existing, PortalType portal, MenuDefinitionDto payload) - { - // 1. 构造实体 - var entity = existing ?? new MenuDefinition - { - Portal = portal, - CreatedAt = DateTime.UtcNow - }; - - // 2. 填充字段 - FillEntity(entity, payload); - - // 3. 返回 DTO 映射 - return ToDto(entity); - } - - /// - /// 将权限/角色集合合并为存储字符串。 - /// - /// 编码集合。 - /// 逗号分隔字符串。 - public static string JoinCodes(IEnumerable codes) - { - return string.Join(',', codes.Where(x => !string.IsNullOrWhiteSpace(x)).Select(x => x.Trim()).Distinct(StringComparer.OrdinalIgnoreCase)); - } - - /// - /// 将逗号分隔编码拆分为集合。 - /// - /// 编码字符串。 - /// 编码数组。 - public static string[] SplitCodes(string? codes) - { - if (string.IsNullOrWhiteSpace(codes)) - { - return Array.Empty(); - } - - return codes - .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToArray(); - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/PermissionTreeQueryHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/PermissionTreeQueryHandler.cs deleted file mode 100644 index 64ef3e3..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/PermissionTreeQueryHandler.cs +++ /dev/null @@ -1,74 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Application.Identity.Queries; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 权限树查询处理器。 -/// -public sealed class PermissionTreeQueryHandler( - IPermissionRepository permissionRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - /// - /// 构建权限树。 - /// - /// 查询参数。 - /// 取消标记。 - /// 权限树列表。 - public async Task> Handle(PermissionTreeQuery request, CancellationToken cancellationToken) - { - // 1. 获取租户上下文并查询权限 - var tenantId = tenantProvider.GetCurrentTenantId(); - var permissions = await permissionRepository.SearchAsync(tenantId, request.Keyword, cancellationToken); - - // 2. 构建节点映射与父子分组 - var nodeMap = permissions.ToDictionary( - x => x.Id, - x => new PermissionTreeDto - { - Id = x.Id, - ParentId = x.ParentId, - SortOrder = x.SortOrder, - Type = x.Type, - Name = x.Name, - Code = x.Code, - Description = x.Description, - Children = Array.Empty() - }); - var childrenLookup = permissions - .GroupBy(x => x.ParentId) - .ToDictionary(g => g.Key, g => g.OrderBy(c => c.SortOrder).ThenBy(c => c.Id).Select(c => c.Id).ToList()); - - // 3. 递归组装树,确保子节点引用最新 - List Build(long parentId) - { - if (!childrenLookup.TryGetValue(parentId, out var childIds)) - { - return []; - } - - var result = new List(childIds.Count); - foreach (var childId in childIds) - { - if (!nodeMap.TryGetValue(childId, out var child)) - { - continue; - } - - var withChildren = child with { Children = Build(child.Id) }; - result.Add(withChildren); - } - - return result; - } - - // 4. 返回根节点集合 - var roots = Build(0); - return roots; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/ResetAdminPasswordByTokenCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/ResetAdminPasswordByTokenCommandHandler.cs deleted file mode 100644 index cd7a0a5..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/ResetAdminPasswordByTokenCommandHandler.cs +++ /dev/null @@ -1,64 +0,0 @@ -using MediatR; -using Microsoft.AspNetCore.Identity; -using TakeoutSaaS.Application.Identity.Abstractions; -using TakeoutSaaS.Application.Identity.Commands; -using TakeoutSaaS.Domain.Identity.Entities; -using TakeoutSaaS.Domain.Identity.Enums; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 通过重置链接令牌重置管理员密码处理器。 -/// -public sealed class ResetAdminPasswordByTokenCommandHandler( - IAdminPasswordResetTokenStore tokenStore, - IIdentityUserRepository userRepository, - IPasswordHasher passwordHasher) - : IRequestHandler -{ - /// - public async Task Handle(ResetAdminPasswordByTokenCommand request, CancellationToken cancellationToken) - { - // 1. 参数校验 - var token = request.Token?.Trim() ?? string.Empty; - if (string.IsNullOrWhiteSpace(token)) - { - throw new BusinessException(ErrorCodes.BadRequest, "重置令牌不能为空"); - } - - var password = request.NewPassword?.Trim() ?? string.Empty; - if (string.IsNullOrWhiteSpace(password)) - { - throw new BusinessException(ErrorCodes.BadRequest, "新密码不能为空"); - } - - if (password.Length is < 6 or > 32) - { - throw new BusinessException(ErrorCodes.BadRequest, "新密码长度需为 6~32 位"); - } - - // 2. 校验并消费令牌 - var userId = await tokenStore.ConsumeAsync(token, cancellationToken); - if (!userId.HasValue || userId.Value == 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "重置链接无效或已过期"); - } - - // 3. 获取用户(可更新,强制租户隔离)并写入新密码哈希 - var user = await userRepository.GetForUpdateAsync(userId.Value, cancellationToken) - ?? throw new BusinessException(ErrorCodes.NotFound, "用户不存在"); - - user.PasswordHash = passwordHasher.HashPassword(user, password); - user.MustChangePassword = false; - user.FailedLoginCount = 0; - user.LockedUntil = null; - if (user.Status == IdentityUserStatus.Locked) - { - user.Status = IdentityUserStatus.Active; - } - await userRepository.SaveChangesAsync(cancellationToken); - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/ResetIdentityUserPasswordCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/ResetIdentityUserPasswordCommandHandler.cs deleted file mode 100644 index d1a7eed..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/ResetIdentityUserPasswordCommandHandler.cs +++ /dev/null @@ -1,97 +0,0 @@ -using MediatR; -using System.Text.Json; -using TakeoutSaaS.Application.Identity.Abstractions; -using TakeoutSaaS.Application.Identity.Commands; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Application.Identity.Events; -using TakeoutSaaS.Domain.Identity.Enums; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 生成用户重置密码链接处理器。 -/// -public sealed class ResetIdentityUserPasswordCommandHandler( - IAdminPasswordResetTokenStore tokenStore, - IIdentityUserRepository identityUserRepository, - ITenantProvider tenantProvider, - ICurrentUserAccessor currentUserAccessor, - IAdminAuthService adminAuthService, - IIdentityOperationLogPublisher operationLogPublisher) - : IRequestHandler -{ - /// - public async Task Handle(ResetIdentityUserPasswordCommand request, CancellationToken cancellationToken) - { - // 1. 获取当前租户与操作者档案 - var currentTenantId = tenantProvider.GetCurrentTenantId(); - var operatorProfile = await adminAuthService.GetProfileAsync(currentUserAccessor.UserId, cancellationToken); - - // 2. 校验跨租户访问 - if (request.TenantId.HasValue && request.TenantId.Value != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户重置密码"); - } - - // 3. 查询用户实体 - var user = await identityUserRepository.GetForUpdateAsync(request.UserId, cancellationToken); - if (user == null) - { - throw new BusinessException(ErrorCodes.NotFound, "用户不存在"); - } - - if (user.TenantId != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户重置密码"); - } - - // 4. 签发重置令牌(1 小时有效) - var expiresAt = DateTime.UtcNow.AddHours(1); - var token = await tokenStore.IssueAsync(user.Id, expiresAt, cancellationToken); - - // 5. 标记用户需重置密码 - user.MustChangePassword = true; - user.FailedLoginCount = 0; - user.LockedUntil = null; - if (user.Status == IdentityUserStatus.Locked) - { - user.Status = IdentityUserStatus.Active; - } - - // 6. 构建操作日志消息 - var operatorName = string.IsNullOrWhiteSpace(operatorProfile.DisplayName) - ? operatorProfile.Account - : operatorProfile.DisplayName; - if (string.IsNullOrWhiteSpace(operatorName)) - { - operatorName = $"user:{currentUserAccessor.UserId}"; - } - - var logMessage = new IdentityUserOperationLogMessage - { - OperationType = "identity-user:password-reset", - TargetType = "identity_user", - TargetIds = JsonSerializer.Serialize(new[] { user.Id }), - OperatorId = currentUserAccessor.UserId.ToString(), - OperatorName = operatorName, - Parameters = JsonSerializer.Serialize(new { userId = user.Id, tenantId = user.TenantId }), - Result = JsonSerializer.Serialize(new { userId = user.Id, expiresAt }), - Success = true - }; - - // 7. 写入 Outbox 并保存变更 - await operationLogPublisher.PublishAsync(logMessage, cancellationToken); - await identityUserRepository.SaveChangesAsync(cancellationToken); - - return new ResetIdentityUserPasswordResult - { - Token = token, - ExpiresAt = expiresAt - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/RestoreIdentityUserCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/RestoreIdentityUserCommandHandler.cs deleted file mode 100644 index 54daabb..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/RestoreIdentityUserCommandHandler.cs +++ /dev/null @@ -1,84 +0,0 @@ -using MediatR; -using System.Text.Json; -using TakeoutSaaS.Application.Identity.Abstractions; -using TakeoutSaaS.Application.Identity.Commands; -using TakeoutSaaS.Application.Identity.Events; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 恢复用户处理器。 -/// -public sealed class RestoreIdentityUserCommandHandler( - IIdentityUserRepository identityUserRepository, - ITenantProvider tenantProvider, - ICurrentUserAccessor currentUserAccessor, - IAdminAuthService adminAuthService, - IIdentityOperationLogPublisher operationLogPublisher) - : IRequestHandler -{ - /// - public async Task Handle(RestoreIdentityUserCommand request, CancellationToken cancellationToken) - { - // 1. 获取当前租户与操作者档案 - var currentTenantId = tenantProvider.GetCurrentTenantId(); - var operatorProfile = await adminAuthService.GetProfileAsync(currentUserAccessor.UserId, cancellationToken); - - // 2. 校验跨租户访问 - if (request.TenantId.HasValue && request.TenantId.Value != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户恢复用户"); - } - - // 3. 查询用户实体(包含已删除) - var user = await identityUserRepository.GetForUpdateIncludingDeletedAsync(currentTenantId, request.UserId, cancellationToken); - if (user == null) - { - return false; - } - - if (user.TenantId != currentTenantId) - { - return false; - } - - if (!user.DeletedAt.HasValue) - { - return false; - } - - // 4. 构建操作日志消息 - var operatorName = string.IsNullOrWhiteSpace(operatorProfile.DisplayName) - ? operatorProfile.Account - : operatorProfile.DisplayName; - if (string.IsNullOrWhiteSpace(operatorName)) - { - operatorName = $"user:{currentUserAccessor.UserId}"; - } - - var logMessage = new IdentityUserOperationLogMessage - { - OperationType = "identity-user:restore", - TargetType = "identity_user", - TargetIds = JsonSerializer.Serialize(new[] { user.Id }), - OperatorId = currentUserAccessor.UserId.ToString(), - OperatorName = operatorName, - Parameters = JsonSerializer.Serialize(new { userId = user.Id, tenantId = user.TenantId }), - Result = JsonSerializer.Serialize(new { userId = user.Id }), - Success = true - }; - - // 5. 恢复软删除状态并写入 Outbox - user.DeletedAt = null; - user.DeletedBy = null; - await operationLogPublisher.PublishAsync(logMessage, cancellationToken); - await identityUserRepository.SaveChangesAsync(cancellationToken); - - return true; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/RoleDetailQueryHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/RoleDetailQueryHandler.cs deleted file mode 100644 index daf567b..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/RoleDetailQueryHandler.cs +++ /dev/null @@ -1,78 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Application.Identity.Queries; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 角色详情查询处理器。 -/// -public sealed class RoleDetailQueryHandler( - IRoleRepository roleRepository, - IRolePermissionRepository rolePermissionRepository, - IPermissionRepository permissionRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - public async Task Handle(RoleDetailQuery request, CancellationToken cancellationToken) - { - // 1. 获取租户上下文并校验跨租户 - var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (currentTenantId <= 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识"); - } - - // 2. (空行后) 禁止跨租户查询 - if (request.TenantId.HasValue && request.TenantId.Value != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户查询角色详情"); - } - - // 3. (空行后) 查询角色 - var tenantId = currentTenantId; - var role = await roleRepository.FindByIdAsync(request.RoleId, tenantId, cancellationToken); - if (role is null) - { - return null; - } - - // 4. (空行后) 查询角色权限关系 - var relations = await rolePermissionRepository.GetByRoleIdsAsync(tenantId, new[] { role.Id }, cancellationToken); - var permissionIds = relations.Select(x => x.PermissionId).ToArray(); - - // 5. (空行后) 拉取权限实体 - var permissions = permissionIds.Length == 0 - ? Array.Empty() - : await permissionRepository.GetByIdsAsync(tenantId, permissionIds, cancellationToken); - - // 6. (空行后) 映射 DTO - var permissionDtos = permissions - .Select(x => new PermissionDto - { - Id = x.Id, - ParentId = x.ParentId, - SortOrder = x.SortOrder, - Type = x.Type, - Code = x.Code, - Name = x.Name, - Description = x.Description - }) - .ToList(); - - return new RoleDetailDto - { - Id = role.Id, - TenantId = role.TenantId, - Name = role.Name, - Code = role.Code, - Description = role.Description, - Permissions = permissionDtos - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/RoleTemplatePermissionsQueryHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/RoleTemplatePermissionsQueryHandler.cs deleted file mode 100644 index 0c5df21..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/RoleTemplatePermissionsQueryHandler.cs +++ /dev/null @@ -1,40 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Application.Identity.Queries; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 角色模板权限查询处理器。 -/// -public sealed class RoleTemplatePermissionsQueryHandler(IRoleTemplateRepository roleTemplateRepository) - : IRequestHandler> -{ - /// - public async Task> Handle(RoleTemplatePermissionsQuery request, CancellationToken cancellationToken) - { - // 1. 校验模板存在 - var template = await roleTemplateRepository.FindByCodeAsync(request.TemplateCode, cancellationToken) - ?? throw new BusinessException(ErrorCodes.NotFound, $"角色模板 {request.TemplateCode} 不存在"); - - // 2. 查询模板权限 - var permissions = await roleTemplateRepository.GetPermissionsAsync(template.Id, cancellationToken); - - // 3. 映射 DTO - var dto = permissions - .Where(x => !string.IsNullOrWhiteSpace(x.PermissionCode)) - .Select(x => new PermissionTemplateDto - { - Code = x.PermissionCode, - Name = x.PermissionCode, - Description = x.PermissionCode - }) - .ToList(); - - // 4. 返回权限列表 - return dto; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/SearchIdentityUsersQueryHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/SearchIdentityUsersQueryHandler.cs deleted file mode 100644 index 0ce96c6..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/SearchIdentityUsersQueryHandler.cs +++ /dev/null @@ -1,139 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Application.Identity.Queries; -using TakeoutSaaS.Domain.Identity.Entities; -using TakeoutSaaS.Domain.Identity.Enums; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Results; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 用户分页查询处理器。 -/// -public sealed class SearchIdentityUsersQueryHandler( - IIdentityUserRepository identityUserRepository, - IUserRoleRepository userRoleRepository, - IRoleRepository roleRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - /// - public async Task> Handle(SearchIdentityUsersQuery request, CancellationToken cancellationToken) - { - // 1. 获取当前租户 - var currentTenantId = tenantProvider.GetCurrentTenantId(); - - // 2. 校验跨租户访问 - if (request.TenantId.HasValue && request.TenantId.Value != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户查询用户"); - } - - // 3. 组装查询过滤条件 - var filter = new IdentityUserSearchFilter - { - TenantId = currentTenantId, - Keyword = request.Keyword, - Status = request.Status, - RoleId = request.RoleId, - CreatedAtFrom = request.CreatedAtFrom, - CreatedAtTo = request.CreatedAtTo, - LastLoginFrom = request.LastLoginFrom, - LastLoginTo = request.LastLoginTo, - IncludeDeleted = request.IncludeDeleted, - Page = request.Page, - PageSize = request.PageSize, - SortBy = request.SortBy, - SortDescending = request.SortDescending - }; - - // 4. 执行分页查询 - var (items, total) = await identityUserRepository.SearchPagedAsync(filter, cancellationToken); - if (items.Count == 0) - { - return new PagedResult(Array.Empty(), request.Page, request.PageSize, total); - } - - // 5. 加载角色编码映射 - var roleCodesLookup = await ResolveRoleCodesAsync(items, userRoleRepository, roleRepository, cancellationToken); - - // 6. 组装 DTO - var now = DateTime.UtcNow; - var dtos = items.Select(user => new UserListItemDto - { - UserId = user.Id, - TenantId = user.TenantId, - Account = user.Account, - DisplayName = user.DisplayName, - Avatar = user.Avatar, - Phone = user.Phone, - Email = user.Email, - Status = user.Status, - IsLocked = IsLocked(user, now), - IsDeleted = user.DeletedAt.HasValue, - Roles = roleCodesLookup.TryGetValue(user.Id, out var codes) ? codes : Array.Empty(), - CreatedAt = user.CreatedAt, - LastLoginAt = user.LastLoginAt - }).ToList(); - - // 7. 返回分页结果 - return new PagedResult(dtos, request.Page, request.PageSize, total); - } - - private static bool IsLocked(IdentityUser user, DateTime now) - => user.Status == IdentityUserStatus.Locked - || (user.LockedUntil.HasValue && user.LockedUntil.Value > now); - - private static async Task> ResolveRoleCodesAsync( - IReadOnlyList users, - IUserRoleRepository userRoleRepository, - IRoleRepository roleRepository, - CancellationToken cancellationToken) - { - // 1. 预分配字典容量 - var result = new Dictionary(users.Count); - - // 2. 按租户分组,降低角色查询次数 - foreach (var group in users.GroupBy(user => user.TenantId)) - { - var tenantId = group.Key; - var userIds = group.Select(user => user.Id).Distinct().ToArray(); - if (userIds.Length == 0) - { - continue; - } - - // 3. 查询用户角色映射 - var relations = await userRoleRepository.GetByUserIdsAsync(tenantId, userIds, cancellationToken); - if (relations.Count == 0) - { - continue; - } - - // 4. 查询角色并构建映射 - var roleIds = relations.Select(x => x.RoleId).Distinct().ToArray(); - var roles = roleIds.Length == 0 - ? Array.Empty() - : await roleRepository.GetByIdsAsync(tenantId, roleIds, cancellationToken); - var roleCodeMap = roles.ToDictionary(role => role.Id, role => role.Code, EqualityComparer.Default); - - // 5. 组装用户角色编码列表 - foreach (var relationGroup in relations.GroupBy(x => x.UserId)) - { - var codes = relationGroup - .Select(x => roleCodeMap.TryGetValue(x.RoleId, out var code) ? code : null) - .OfType() - .Where(code => !string.IsNullOrWhiteSpace(code)) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToArray(); - result[relationGroup.Key] = codes.Length == 0 ? Array.Empty() : codes; - } - } - - return result; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/SearchPermissionsQueryHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/SearchPermissionsQueryHandler.cs deleted file mode 100644 index d31a9ea..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/SearchPermissionsQueryHandler.cs +++ /dev/null @@ -1,74 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Application.Identity.Queries; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Results; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 权限分页查询处理器。 -/// -public sealed class SearchPermissionsQueryHandler( - IPermissionRepository permissionRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - /// - /// 执行权限分页查询。 - /// - /// 查询参数。 - /// 取消标记。 - /// 分页结果。 - public async Task> Handle(SearchPermissionsQuery request, CancellationToken cancellationToken) - { - // 1. 获取租户上下文并查询权限 - var tenantId = tenantProvider.GetCurrentTenantId(); - var permissions = await permissionRepository.SearchAsync(tenantId, request.Keyword, cancellationToken); - - // 2. 排序 - var sorted = request.SortBy?.ToLowerInvariant() switch - { - "name" => request.SortDescending - ? permissions.OrderByDescending(x => x.Name) - : permissions.OrderBy(x => x.Name), - "code" => request.SortDescending - ? permissions.OrderByDescending(x => x.Code) - : permissions.OrderBy(x => x.Code), - "parentid" => request.SortDescending - ? permissions.OrderByDescending(x => x.ParentId).ThenByDescending(x => x.SortOrder) - : permissions.OrderBy(x => x.ParentId).ThenBy(x => x.SortOrder), - "type" => request.SortDescending - ? permissions.OrderByDescending(x => x.Type).ThenByDescending(x => x.SortOrder) - : permissions.OrderBy(x => x.Type).ThenBy(x => x.SortOrder), - "sortorder" => request.SortDescending - ? permissions.OrderByDescending(x => x.SortOrder).ThenByDescending(x => x.CreatedAt) - : permissions.OrderBy(x => x.SortOrder).ThenBy(x => x.CreatedAt), - _ => request.SortDescending - ? permissions.OrderByDescending(x => x.SortOrder).ThenByDescending(x => x.CreatedAt) - : permissions.OrderBy(x => x.SortOrder).ThenBy(x => x.CreatedAt) - }; - - // 3. 分页 - var paged = sorted - .Skip((request.Page - 1) * request.PageSize) - .Take(request.PageSize) - .ToList(); - - // 4. 映射 DTO - var items = paged.Select(permission => new PermissionDto - { - Id = permission.Id, - ParentId = permission.ParentId, - SortOrder = permission.SortOrder, - Type = permission.Type, - Name = permission.Name, - Code = permission.Code, - Description = permission.Description - }).ToList(); - - // 5. 返回分页结果 - return new PagedResult(items, request.Page, request.PageSize, permissions.Count); - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/SearchRolesQueryHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/SearchRolesQueryHandler.cs deleted file mode 100644 index 0e0f575..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/SearchRolesQueryHandler.cs +++ /dev/null @@ -1,75 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Application.Identity.Queries; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Results; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 角色分页查询处理器。 -/// -public sealed class SearchRolesQueryHandler( - IRoleRepository roleRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - /// - /// 执行角色分页查询。 - /// - /// 查询参数。 - /// 取消标记。 - /// 分页结果。 - public async Task> Handle(SearchRolesQuery request, CancellationToken cancellationToken) - { - // 1. 获取租户上下文并校验跨租户 - var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (currentTenantId <= 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识"); - } - - // 2. (空行后) 禁止跨租户查询 - if (request.TenantId.HasValue && request.TenantId.Value != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户查询角色"); - } - - // 3. (空行后) 查询角色列表 - var tenantId = currentTenantId; - var roles = await roleRepository.SearchAsync(tenantId, request.Keyword, cancellationToken); - - // 4. (空行后) 排序 - var sorted = request.SortBy?.ToLowerInvariant() switch - { - "name" => request.SortDescending - ? roles.OrderByDescending(x => x.Name) - : roles.OrderBy(x => x.Name), - _ => request.SortDescending - ? roles.OrderByDescending(x => x.CreatedAt) - : roles.OrderBy(x => x.CreatedAt) - }; - - // 5. (空行后) 分页 - var paged = sorted - .Skip((request.Page - 1) * request.PageSize) - .Take(request.PageSize) - .ToList(); - - // 6. (空行后) 映射 DTO - var items = paged.Select(role => new RoleDto - { - Id = role.Id, - TenantId = role.TenantId, - Name = role.Name, - Code = role.Code, - Description = role.Description - }).ToList(); - - // 7. (空行后) 返回分页结果 - return new PagedResult(items, request.Page, request.PageSize, roles.Count); - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/SearchUserPermissionsQueryHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/SearchUserPermissionsQueryHandler.cs deleted file mode 100644 index 4184be8..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/SearchUserPermissionsQueryHandler.cs +++ /dev/null @@ -1,129 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Application.Identity.Queries; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Results; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 租户用户权限分页查询处理器。 -/// -public sealed class SearchUserPermissionsQueryHandler( - IIdentityUserRepository identityUserRepository, - IUserRoleRepository userRoleRepository, - IRoleRepository roleRepository, - IPermissionRepository permissionRepository, - IRolePermissionRepository rolePermissionRepository, - ITenantProvider tenantProvider) - : IRequestHandler> -{ - /// - public async Task> Handle(SearchUserPermissionsQuery request, CancellationToken cancellationToken) - { - // 1. 获取租户并查询用户 - var tenantId = tenantProvider.GetCurrentTenantId(); - var users = await identityUserRepository.SearchAsync(tenantId, request.Keyword, cancellationToken); - - // 2. 排序与分页 - var sorted = SortUsers(users, request.SortBy, request.SortDescending); - var paged = sorted - .Skip((request.Page - 1) * request.PageSize) - .Take(request.PageSize) - .ToList(); - - // 3. 解析角色与权限 - var resolved = await ResolveRolesAndPermissionsAsync(tenantId, paged, cancellationToken); - var items = paged.Select(user => new UserPermissionDto - { - UserId = user.Id, - TenantId = user.TenantId, - MerchantId = user.MerchantId, - Account = user.Account, - DisplayName = user.DisplayName, - Roles = resolved[user.Id].roles, - Permissions = resolved[user.Id].permissions, - CreatedAt = user.CreatedAt - }).ToList(); - - return new PagedResult(items, request.Page, request.PageSize, users.Count); - } - - private static IOrderedEnumerable SortUsers( - IReadOnlyCollection users, - string? sortBy, - bool sortDescending) - { - return sortBy?.ToLowerInvariant() switch - { - "account" => sortDescending - ? users.OrderByDescending(x => x.Account) - : users.OrderBy(x => x.Account), - "displayname" => sortDescending - ? users.OrderByDescending(x => x.DisplayName) - : users.OrderBy(x => x.DisplayName), - _ => sortDescending - ? users.OrderByDescending(x => x.CreatedAt) - : users.OrderBy(x => x.CreatedAt) - }; - } - - private async Task> ResolveRolesAndPermissionsAsync( - long tenantId, - IReadOnlyCollection users, - CancellationToken cancellationToken) - { - // 1. 查询用户角色关系 - var userIds = users.Select(x => x.Id).ToArray(); - var userRoleRelations = await userRoleRepository.GetByUserIdsAsync(tenantId, userIds, cancellationToken); - var roleIds = userRoleRelations.Select(x => x.RoleId).Distinct().ToArray(); - - // 2. 查询角色信息 - var roles = roleIds.Length == 0 - ? Array.Empty() - : await roleRepository.GetByIdsAsync(tenantId, roleIds, cancellationToken); - var roleCodeMap = roles.ToDictionary(r => r.Id, r => r.Code, comparer: EqualityComparer.Default); - - // 3. 查询角色-权限关系 - var rolePermissions = roleIds.Length == 0 - ? Array.Empty() - : await rolePermissionRepository.GetByRoleIdsAsync(tenantId, roleIds, cancellationToken); - var permissionIds = rolePermissions.Select(x => x.PermissionId).Distinct().ToArray(); - - // 4. 查询权限详情 - var permissions = permissionIds.Length == 0 - ? Array.Empty() - : await permissionRepository.GetByIdsAsync(tenantId, permissionIds, cancellationToken); - var permissionCodeMap = permissions.ToDictionary(p => p.Id, p => p.Code, comparer: EqualityComparer.Default); - - var rolePermissionsLookup = rolePermissions - .GroupBy(rp => rp.RoleId) - .ToDictionary(g => g.Key, g => g.Select(rp => rp.PermissionId).ToArray(), comparer: EqualityComparer.Default); - - var result = new Dictionary(); - foreach (var userId in userIds) - { - // 5. 聚合用户角色与权限编码 - var rolesForUser = userRoleRelations.Where(ur => ur.UserId == userId).Select(ur => ur.RoleId).Distinct().ToArray(); - var roleCodes = rolesForUser - .Select(rid => roleCodeMap.GetValueOrDefault(rid)) - .Where(c => !string.IsNullOrWhiteSpace(c)) - .Select(c => c!) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToArray(); - - var permissionCodes = rolesForUser - .SelectMany(rid => rolePermissionsLookup.GetValueOrDefault(rid) ?? Array.Empty()) - .Select(pid => permissionCodeMap.GetValueOrDefault(pid)) - .Where(code => !string.IsNullOrWhiteSpace(code)) - .Select(code => code!) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToArray(); - - result[userId] = (roleCodes, permissionCodes); - } - - return result; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/TemplateMapper.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/TemplateMapper.cs deleted file mode 100644 index aaf6d71..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/TemplateMapper.cs +++ /dev/null @@ -1,35 +0,0 @@ -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Domain.Identity.Entities; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 模板 DTO 映射工具。 -/// -internal static class TemplateMapper -{ - /// - /// 将角色模板与权限编码集合映射为 DTO。 - /// - /// 角色模板实体。 - /// 权限编码集合。 - /// 模板 DTO。 - public static RoleTemplateDto ToDto(RoleTemplate template, IReadOnlyCollection permissionCodes) - { - return new RoleTemplateDto - { - TemplateCode = template.TemplateCode, - Name = template.Name, - Description = template.Description, - IsActive = template.IsActive, - Permissions = permissionCodes - .Select(code => new PermissionTemplateDto - { - Code = code, - Name = code, - Description = null - }) - .ToArray() - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateIdentityUserCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateIdentityUserCommandHandler.cs deleted file mode 100644 index 665ee40..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateIdentityUserCommandHandler.cs +++ /dev/null @@ -1,166 +0,0 @@ -using MediatR; -using System.Text.Json; -using TakeoutSaaS.Application.Identity.Abstractions; -using TakeoutSaaS.Application.Identity.Commands; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Application.Identity.Events; -using TakeoutSaaS.Application.Identity.Queries; -using TakeoutSaaS.Domain.Identity.Entities; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 更新用户处理器。 -/// -public sealed class UpdateIdentityUserCommandHandler( - IIdentityUserRepository identityUserRepository, - IUserRoleRepository userRoleRepository, - IRoleRepository roleRepository, - ITenantProvider tenantProvider, - ICurrentUserAccessor currentUserAccessor, - IAdminAuthService adminAuthService, - IIdentityOperationLogPublisher operationLogPublisher, - IMediator mediator) - : IRequestHandler -{ - /// - public async Task Handle(UpdateIdentityUserCommand request, CancellationToken cancellationToken) - { - // 1. 获取当前租户与操作者档案 - var currentTenantId = tenantProvider.GetCurrentTenantId(); - var operatorProfile = await adminAuthService.GetProfileAsync(currentUserAccessor.UserId, cancellationToken); - - // 2. 校验跨租户访问 - if (request.TenantId.HasValue && request.TenantId.Value != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户更新用户"); - } - - // 3. 获取用户实体 - var user = await identityUserRepository.GetForUpdateAsync(request.UserId, cancellationToken); - if (user == null) - { - return null; - } - - if (user.TenantId != currentTenantId) - { - return null; - } - - // 4. 规范化输入并校验唯一性 - var displayName = request.DisplayName.Trim(); - var phone = string.IsNullOrWhiteSpace(request.Phone) ? null : request.Phone.Trim(); - var email = string.IsNullOrWhiteSpace(request.Email) ? null : request.Email.Trim(); - var roleIds = request.RoleIds == null ? null : ParseIds(request.RoleIds, "角色"); - - if (!string.IsNullOrWhiteSpace(phone) - && !string.Equals(phone, user.Phone, StringComparison.OrdinalIgnoreCase) - && await identityUserRepository.ExistsByPhoneAsync(user.TenantId, phone, user.Id, cancellationToken)) - { - throw new BusinessException(ErrorCodes.Conflict, "手机号已存在"); - } - - if (!string.IsNullOrWhiteSpace(email) - && !string.Equals(email, user.Email, StringComparison.OrdinalIgnoreCase) - && await identityUserRepository.ExistsByEmailAsync(user.TenantId, email, user.Id, cancellationToken)) - { - throw new BusinessException(ErrorCodes.Conflict, "邮箱已存在"); - } - - if (roleIds is { Length: > 0 }) - { - var roles = await roleRepository.GetByIdsAsync(user.TenantId, roleIds, cancellationToken); - if (roles.Count != roleIds.Length) - { - throw new BusinessException(ErrorCodes.BadRequest, "角色列表包含无效项"); - } - } - - // 5. 更新用户字段 - user.DisplayName = displayName; - user.Phone = phone; - user.Email = email; - user.Avatar = string.IsNullOrWhiteSpace(request.Avatar) ? null : request.Avatar.Trim(); - - // 6. 构建操作日志消息 - var operatorName = string.IsNullOrWhiteSpace(operatorProfile.DisplayName) - ? operatorProfile.Account - : operatorProfile.DisplayName; - if (string.IsNullOrWhiteSpace(operatorName)) - { - operatorName = $"user:{currentUserAccessor.UserId}"; - } - - var logMessage = new IdentityUserOperationLogMessage - { - OperationType = "identity-user:update", - TargetType = "identity_user", - TargetIds = JsonSerializer.Serialize(new[] { user.Id }), - OperatorId = currentUserAccessor.UserId.ToString(), - OperatorName = operatorName, - Parameters = JsonSerializer.Serialize(new - { - userId = user.Id, - displayName, - phone, - email, - roleIds - }), - Result = JsonSerializer.Serialize(new { userId = user.Id }), - Success = true - }; - - // 7. 持久化用户更新并写入 Outbox - try - { - await operationLogPublisher.PublishAsync(logMessage, cancellationToken); - await identityUserRepository.SaveChangesAsync(cancellationToken); - } - catch (Exception ex) when (IsConcurrencyException(ex)) - { - throw new BusinessException(ErrorCodes.Conflict, "用户数据已被修改,请刷新后重试"); - } - - // 8. 覆盖角色绑定(仅当显式传入时) - if (roleIds != null) - { - await userRoleRepository.ReplaceUserRolesAsync(user.TenantId, user.Id, roleIds, cancellationToken); - } - - // 9. 返回用户详情 - return await mediator.Send(new GetIdentityUserDetailQuery { UserId = user.Id }, cancellationToken); - } - - private static long[] ParseIds(string[] values, string name) - { - // 1. 空数组直接返回 - if (values.Length == 0) - { - return Array.Empty(); - } - - // 2. 解析并去重 - var ids = new List(values.Length); - foreach (var value in values) - { - if (!long.TryParse(value, out var id) || id <= 0) - { - throw new BusinessException(ErrorCodes.BadRequest, $"{name} ID 无效"); - } - - ids.Add(id); - } - - // 3. 返回去重结果 - return ids.Distinct().ToArray(); - } - - private static bool IsConcurrencyException(Exception exception) - => string.Equals(exception.GetType().Name, "DbUpdateConcurrencyException", StringComparison.Ordinal); -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateMenuCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateMenuCommandHandler.cs deleted file mode 100644 index 37019b9..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateMenuCommandHandler.cs +++ /dev/null @@ -1,55 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity; -using TakeoutSaaS.Application.Identity.Commands; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 更新菜单处理器。 -/// -public sealed class UpdateMenuCommandHandler(IMenuRepository menuRepository) - : IRequestHandler -{ - /// - public async Task Handle(UpdateMenuCommand request, CancellationToken cancellationToken) - { - // 1. 菜单固定时禁止修改 - if (!MenuPolicy.CanMaintainMenus) - { - throw new BusinessException(ErrorCodes.Forbidden, "菜单已固定,禁止修改"); - } - - // 2. 校验存在 - var entity = await menuRepository.FindByIdAsync(request.Id, cancellationToken) - ?? throw new BusinessException(ErrorCodes.NotFound, "菜单不存在"); - - // 3. 更新字段 - entity.ParentId = request.ParentId; - entity.Name = request.Name.Trim(); - entity.Path = request.Path.Trim(); - entity.Component = request.Component.Trim(); - entity.Title = request.Title.Trim(); - entity.Icon = request.Icon?.Trim(); - entity.IsIframe = request.IsIframe; - entity.Link = string.IsNullOrWhiteSpace(request.Link) ? null : request.Link.Trim(); - entity.KeepAlive = request.KeepAlive; - entity.SortOrder = request.SortOrder; - entity.RequiredPermissions = MenuMapper.JoinCodes(request.RequiredPermissions); - entity.MetaPermissions = MenuMapper.JoinCodes(request.MetaPermissions); - entity.MetaRoles = MenuMapper.JoinCodes(request.MetaRoles); - entity.AuthListJson = request.AuthList.Count == 0 - ? null - : System.Text.Json.JsonSerializer.Serialize(request.AuthList); - - // 4. 持久化 - await menuRepository.UpdateAsync(entity, cancellationToken); - await menuRepository.SaveChangesAsync(cancellationToken); - - // 5. 返回 DTO - return MenuMapper.ToDto(entity); - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdatePermissionCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdatePermissionCommandHandler.cs deleted file mode 100644 index d108dde..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdatePermissionCommandHandler.cs +++ /dev/null @@ -1,72 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Commands; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 更新权限处理器。 -/// -public sealed class UpdatePermissionCommandHandler( - IPermissionRepository permissionRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - /// 执行权限更新。 - /// - /// 更新命令。 - /// 取消标记。 - /// 更新后的权限 DTO 或 null。 - public async Task Handle(UpdatePermissionCommand request, CancellationToken cancellationToken) - { - // 1. 权限固定时禁止修改 - if (!PermissionPolicy.CanMaintainPermissions) - { - throw new BusinessException(ErrorCodes.Forbidden, "权限已固定,禁止修改"); - } - - // 2. 获取租户上下文并查询权限 - var tenantId = tenantProvider.GetCurrentTenantId(); - var permission = await permissionRepository.FindByIdAsync(request.PermissionId, tenantId, cancellationToken); - if (permission == null) - { - return null; - } - - // 3. 更新字段 - var normalizedType = string.IsNullOrWhiteSpace(request.Type) - ? "leaf" - : request.Type.Trim().ToLowerInvariant(); - normalizedType = normalizedType is "group" or "leaf" ? normalizedType : "leaf"; - var parentId = request.ParentId > 0 && request.ParentId != permission.Id - ? request.ParentId - : 0; - var sortOrder = request.SortOrder < 0 ? 0 : request.SortOrder; - permission.ParentId = parentId; - permission.SortOrder = sortOrder; - permission.Type = normalizedType; - permission.Name = request.Name; - permission.Description = request.Description; - - // 4. 持久化 - await permissionRepository.UpdateAsync(permission, cancellationToken); - await permissionRepository.SaveChangesAsync(cancellationToken); - - // 5. 返回 DTO - return new PermissionDto - { - Id = permission.Id, - ParentId = permission.ParentId, - SortOrder = permission.SortOrder, - Type = permission.Type, - Name = permission.Name, - Code = permission.Code, - Description = permission.Description - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateRoleCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateRoleCommandHandler.cs deleted file mode 100644 index 01f7b67..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateRoleCommandHandler.cs +++ /dev/null @@ -1,66 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Commands; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 更新角色处理器。 -/// -public sealed class UpdateRoleCommandHandler( - IRoleRepository roleRepository, - ITenantProvider tenantProvider) - : IRequestHandler -{ - /// - /// 执行角色更新。 - /// - /// 更新命令。 - /// 取消标记。 - /// 更新后的角色 DTO 或 null。 - public async Task Handle(UpdateRoleCommand request, CancellationToken cancellationToken) - { - // 1. 获取租户上下文并校验跨租户 - var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (currentTenantId <= 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识"); - } - - // 2. (空行后) 禁止跨租户更新 - if (request.TenantId.HasValue && request.TenantId.Value != currentTenantId) - { - throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户更新角色"); - } - - // 3. (空行后) 查询角色 - var tenantId = currentTenantId; - var role = await roleRepository.FindByIdAsync(request.RoleId, tenantId, cancellationToken); - if (role == null) - { - return null; - } - - // 4. (空行后) 更新字段 - role.Name = request.Name; - role.Description = request.Description; - - // 5. (空行后) 持久化 - await roleRepository.UpdateAsync(role, cancellationToken); - await roleRepository.SaveChangesAsync(cancellationToken); - - // 6. (空行后) 返回 DTO - return new RoleDto - { - Id = role.Id, - TenantId = role.TenantId, - Name = role.Name, - Code = role.Code, - Description = role.Description - }; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateRoleTemplateCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateRoleTemplateCommandHandler.cs deleted file mode 100644 index a98bf6e..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateRoleTemplateCommandHandler.cs +++ /dev/null @@ -1,45 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Commands; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; - -namespace TakeoutSaaS.Application.Identity.Handlers; - -/// -/// 更新角色模板处理器。 -/// -public sealed class UpdateRoleTemplateCommandHandler(IRoleTemplateRepository roleTemplateRepository) - : IRequestHandler -{ - /// - public async Task Handle(UpdateRoleTemplateCommand request, CancellationToken cancellationToken) - { - if (string.IsNullOrWhiteSpace(request.TemplateCode) || string.IsNullOrWhiteSpace(request.Name)) - { - throw new BusinessException(ErrorCodes.BadRequest, "模板编码与名称不能为空"); - } - - var template = await roleTemplateRepository.FindByCodeAsync(request.TemplateCode, cancellationToken); - if (template == null) - { - return null; - } - - template.Name = request.Name.Trim(); - template.Description = request.Description; - template.IsActive = request.IsActive; - - var permissions = request.PermissionCodes - .Where(code => !string.IsNullOrWhiteSpace(code)) - .Select(code => code.Trim()) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToArray(); - - await roleTemplateRepository.UpdateAsync(template, permissions, cancellationToken); - await roleTemplateRepository.SaveChangesAsync(cancellationToken); - - return TemplateMapper.ToDto(template, permissions); - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/MenuPolicy.cs b/src/Application/TakeoutSaaS.Application/Identity/MenuPolicy.cs deleted file mode 100644 index 4b8022b..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/MenuPolicy.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace TakeoutSaaS.Application.Identity; - -/// -/// 菜单维护策略(固定菜单时禁用增删改)。 -/// -public static class MenuPolicy -{ - /// - /// 是否允许维护菜单(创建/更新/删除)。 - /// - public static bool CanMaintainMenus { get; } = false; -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Models/IdentityUserBatchOperation.cs b/src/Application/TakeoutSaaS.Application/Identity/Models/IdentityUserBatchOperation.cs deleted file mode 100644 index 017d489..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Models/IdentityUserBatchOperation.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace TakeoutSaaS.Application.Identity.Models; - -/// -/// 批量用户操作类型。 -/// -public enum IdentityUserBatchOperation -{ - /// - /// 启用。 - /// - Enable = 1, - - /// - /// 禁用。 - /// - Disable = 2, - - /// - /// 删除。 - /// - Delete = 3, - - /// - /// 恢复。 - /// - Restore = 4, - - /// - /// 导出。 - /// - Export = 5 -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/PermissionPolicy.cs b/src/Application/TakeoutSaaS.Application/Identity/PermissionPolicy.cs deleted file mode 100644 index bec054c..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/PermissionPolicy.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace TakeoutSaaS.Application.Identity; - -/// -/// 权限管理策略。 -/// -public static class PermissionPolicy -{ - /// - /// 是否允许维护权限定义(固定权限时为 false)。 - /// - public static bool CanMaintainPermissions => false; -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Queries/GetIdentityUserDetailQuery.cs b/src/Application/TakeoutSaaS.Application/Identity/Queries/GetIdentityUserDetailQuery.cs deleted file mode 100644 index f812bc8..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Queries/GetIdentityUserDetailQuery.cs +++ /dev/null @@ -1,20 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; - -namespace TakeoutSaaS.Application.Identity.Queries; - -/// -/// 获取用户详情。 -/// -public sealed record GetIdentityUserDetailQuery : IRequest -{ - /// - /// 用户 ID。 - /// - public long UserId { get; init; } - - /// - /// 是否包含已删除用户。 - /// - public bool IncludeDeleted { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Queries/GetRoleTemplateQuery.cs b/src/Application/TakeoutSaaS.Application/Identity/Queries/GetRoleTemplateQuery.cs deleted file mode 100644 index b282312..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Queries/GetRoleTemplateQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; - -namespace TakeoutSaaS.Application.Identity.Queries; - -/// -/// 获取单个角色模板详情。 -/// -public sealed record GetRoleTemplateQuery : IRequest -{ - /// - /// 模板编码。 - /// - public string TemplateCode { get; init; } = string.Empty; -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Queries/GetUserPermissionsQuery.cs b/src/Application/TakeoutSaaS.Application/Identity/Queries/GetUserPermissionsQuery.cs deleted file mode 100644 index 84b11d2..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Queries/GetUserPermissionsQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; - -namespace TakeoutSaaS.Application.Identity.Queries; - -/// -/// 按用户 ID 获取角色/权限概览。 -/// -public sealed class GetUserPermissionsQuery : IRequest -{ - /// - /// 用户 ID(雪花)。 - /// - public long UserId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Queries/ListMenusQuery.cs b/src/Application/TakeoutSaaS.Application/Identity/Queries/ListMenusQuery.cs deleted file mode 100644 index 429582b..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Queries/ListMenusQuery.cs +++ /dev/null @@ -1,12 +0,0 @@ -using MediatR; -using System.Collections.Generic; -using TakeoutSaaS.Application.Identity.Contracts; - -namespace TakeoutSaaS.Application.Identity.Queries; - -/// -/// 查询菜单列表(当前租户)。 -/// -public sealed class ListMenusQuery : IRequest> -{ -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Queries/ListRoleTemplatesQuery.cs b/src/Application/TakeoutSaaS.Application/Identity/Queries/ListRoleTemplatesQuery.cs deleted file mode 100644 index 1b76a6d..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Queries/ListRoleTemplatesQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; - -namespace TakeoutSaaS.Application.Identity.Queries; - -/// -/// 查询角色模板列表。 -/// -public sealed record ListRoleTemplatesQuery : IRequest> -{ - /// - /// 是否仅返回启用模板。 - /// - public bool? IsActive { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Queries/MenuDetailQuery.cs b/src/Application/TakeoutSaaS.Application/Identity/Queries/MenuDetailQuery.cs deleted file mode 100644 index 8809800..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Queries/MenuDetailQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; - -namespace TakeoutSaaS.Application.Identity.Queries; - -/// -/// 菜单详情查询。 -/// -public sealed class MenuDetailQuery : IRequest -{ - /// - /// 菜单 ID。 - /// - public long Id { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Queries/PermissionTreeQuery.cs b/src/Application/TakeoutSaaS.Application/Identity/Queries/PermissionTreeQuery.cs deleted file mode 100644 index 5847f02..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Queries/PermissionTreeQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; - -namespace TakeoutSaaS.Application.Identity.Queries; - -/// -/// 权限树查询。 -/// -public sealed class PermissionTreeQuery : IRequest> -{ - /// - /// 关键字(可选)。 - /// - public string? Keyword { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Queries/RoleDetailQuery.cs b/src/Application/TakeoutSaaS.Application/Identity/Queries/RoleDetailQuery.cs deleted file mode 100644 index e1d00ad..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Queries/RoleDetailQuery.cs +++ /dev/null @@ -1,20 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; - -namespace TakeoutSaaS.Application.Identity.Queries; - -/// -/// 查询角色详情(含权限)。 -/// -public sealed class RoleDetailQuery : IRequest -{ - /// - /// 角色 ID。 - /// - public long RoleId { get; init; } - - /// - /// 租户 ID(空则取当前上下文)。 - /// - public long? TenantId { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Queries/RoleTemplatePermissionsQuery.cs b/src/Application/TakeoutSaaS.Application/Identity/Queries/RoleTemplatePermissionsQuery.cs deleted file mode 100644 index ad84c9d..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Queries/RoleTemplatePermissionsQuery.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; - -namespace TakeoutSaaS.Application.Identity.Queries; - -/// -/// 查询角色模板权限列表。 -/// -public sealed class RoleTemplatePermissionsQuery : IRequest> -{ - /// - /// 模板编码。 - /// - public string TemplateCode { get; init; } = string.Empty; -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Queries/SearchIdentityUsersQuery.cs b/src/Application/TakeoutSaaS.Application/Identity/Queries/SearchIdentityUsersQuery.cs deleted file mode 100644 index 9ab3288..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Queries/SearchIdentityUsersQuery.cs +++ /dev/null @@ -1,77 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Domain.Identity.Enums; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.Identity.Queries; - -/// -/// 用户列表查询。 -/// -public sealed record SearchIdentityUsersQuery : IRequest> -{ - /// - /// 租户 ID(可选,默认当前登录租户;禁止跨租户查询)。 - /// - public long? TenantId { get; init; } - - /// - /// 关键字(账号/姓名/手机号/邮箱)。 - /// - public string? Keyword { get; init; } - - /// - /// 用户状态。 - /// - public IdentityUserStatus? Status { get; init; } - - /// - /// 角色 ID。 - /// - public long? RoleId { get; init; } - - /// - /// 创建开始时间(UTC)。 - /// - public DateTime? CreatedAtFrom { get; init; } - - /// - /// 创建结束时间(UTC)。 - /// - public DateTime? CreatedAtTo { get; init; } - - /// - /// 最近登录开始时间(UTC)。 - /// - public DateTime? LastLoginFrom { get; init; } - - /// - /// 最近登录结束时间(UTC)。 - /// - public DateTime? LastLoginTo { get; init; } - - /// - /// 是否包含已删除用户。 - /// - public bool IncludeDeleted { get; init; } - - /// - /// 页码(从 1 开始)。 - /// - public int Page { get; init; } = 1; - - /// - /// 每页条数。 - /// - public int PageSize { get; init; } = 20; - - /// - /// 排序字段。 - /// - public string? SortBy { get; init; } - - /// - /// 是否降序。 - /// - public bool SortDescending { get; init; } = true; -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Queries/SearchPermissionsQuery.cs b/src/Application/TakeoutSaaS.Application/Identity/Queries/SearchPermissionsQuery.cs deleted file mode 100644 index 1987a5a..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Queries/SearchPermissionsQuery.cs +++ /dev/null @@ -1,32 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.Identity.Queries; - -/// -/// 分页查询权限。 -/// -public sealed class SearchPermissionsQuery : IRequest> -{ - /// - /// 搜索关键字。 - /// - public string? Keyword { get; init; } - /// - /// 页码(从 1 开始)。 - /// - public int Page { get; init; } = 1; - /// - /// 每页条数。 - /// - public int PageSize { get; init; } = 20; - /// - /// 排序字段。 - /// - public string? SortBy { get; init; } - /// - /// 是否降序。 - /// - public bool SortDescending { get; init; } = true; -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Queries/SearchRolesQuery.cs b/src/Application/TakeoutSaaS.Application/Identity/Queries/SearchRolesQuery.cs deleted file mode 100644 index 7fccd3a..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Queries/SearchRolesQuery.cs +++ /dev/null @@ -1,37 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.Identity.Queries; - -/// -/// 分页查询角色。 -/// -public sealed class SearchRolesQuery : IRequest> -{ - /// - /// 指定查询的租户 ID(空则取当前上下文)。 - /// - public long? TenantId { get; init; } - - /// - /// 搜索关键字。 - /// - public string? Keyword { get; init; } - /// - /// 页码(从 1 开始)。 - /// - public int Page { get; init; } = 1; - /// - /// 每页条数。 - /// - public int PageSize { get; init; } = 20; - /// - /// 排序字段。 - /// - public string? SortBy { get; init; } - /// - /// 是否降序。 - /// - public bool SortDescending { get; init; } = true; -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Queries/SearchUserPermissionsQuery.cs b/src/Application/TakeoutSaaS.Application/Identity/Queries/SearchUserPermissionsQuery.cs deleted file mode 100644 index 1a6d557..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Queries/SearchUserPermissionsQuery.cs +++ /dev/null @@ -1,36 +0,0 @@ -using MediatR; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Shared.Abstractions.Results; - -namespace TakeoutSaaS.Application.Identity.Queries; - -/// -/// 按租户分页查询用户的角色/权限概览。 -/// -public sealed class SearchUserPermissionsQuery : IRequest> -{ - /// - /// 关键字(账号或展示名称)。 - /// - public string? Keyword { get; init; } - - /// - /// 页码,从 1 开始。 - /// - public int Page { get; init; } = 1; - - /// - /// 每页条数。 - /// - public int PageSize { get; init; } = 20; - - /// - /// 排序字段(account/displayName/createdAt)。 - /// - public string? SortBy { get; init; } - - /// - /// 是否倒序。 - /// - public bool SortDescending { get; init; } = true; -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Services/MiniAuthService.cs b/src/Application/TakeoutSaaS.Application/Identity/Services/MiniAuthService.cs deleted file mode 100644 index 8234d7e..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Services/MiniAuthService.cs +++ /dev/null @@ -1,148 +0,0 @@ -using Microsoft.AspNetCore.Http; -using System.Net; -using TakeoutSaaS.Application.Identity.Abstractions; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Domain.Identity.Entities; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Identity.Services; - -/// -/// 小程序认证服务实现。 -/// -public sealed class MiniAuthService( - IWeChatAuthService weChatAuthService, - IMiniUserRepository miniUserRepository, - IJwtTokenService jwtTokenService, - IRefreshTokenStore refreshTokenStore, - ILoginRateLimiter rateLimiter, - IHttpContextAccessor httpContextAccessor, - ITenantProvider tenantProvider) : IMiniAuthService -{ - /// - /// 微信小程序登录:通过微信 code 获取用户信息并生成令牌。 - /// - /// 微信登录请求 - /// 取消令牌 - /// 令牌响应 - /// 获取微信用户信息失败、缺少租户标识时抛出 - public async Task LoginWithWeChatAsync(WeChatLoginRequest request, CancellationToken cancellationToken = default) - { - // 1. 限流检查(基于 IP 地址) - var throttleKey = BuildThrottleKey(); - await rateLimiter.EnsureAllowedAsync(throttleKey, cancellationToken); - - // 2. 通过微信 code 获取 session(OpenId、UnionId、SessionKey) - var session = await weChatAuthService.Code2SessionAsync(request.Code, cancellationToken); - if (string.IsNullOrWhiteSpace(session.OpenId)) - { - throw new BusinessException(ErrorCodes.Unauthorized, "获取微信用户信息失败"); - } - - // 3. 获取当前租户 ID(多租户支持) - var tenantId = tenantProvider.GetCurrentTenantId(); - if (tenantId == 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识"); - } - - // 4. 获取或创建小程序用户(如果 OpenId 已存在则返回现有用户,否则创建新用户) - var (user, isNew) = await GetOrBindMiniUserAsync(session.OpenId, session.UnionId, request.Nickname, request.Avatar, tenantId, cancellationToken); - - // 5. 登录成功后重置限流计数 - await rateLimiter.ResetAsync(throttleKey, cancellationToken); - - // 6. 构建用户档案并生成令牌 - var profile = BuildProfile(user); - return await jwtTokenService.CreateTokensAsync(profile, isNew, cancellationToken); - } - - /// - /// 刷新访问令牌:使用刷新令牌获取新的访问令牌和刷新令牌。 - /// - /// 刷新令牌请求 - /// 取消令牌 - /// 新的令牌响应 - /// 刷新令牌无效、已过期或用户不存在时抛出 - public async Task RefreshTokenAsync(RefreshTokenRequest request, CancellationToken cancellationToken = default) - { - // 1. 验证刷新令牌(检查是否存在、是否过期、是否已撤销) - var descriptor = await refreshTokenStore.GetAsync(request.RefreshToken, cancellationToken); - if (descriptor == null || descriptor.ExpiresAt <= DateTime.UtcNow || descriptor.Revoked) - { - throw new BusinessException(ErrorCodes.Unauthorized, "RefreshToken 无效或已过期"); - } - - // 2. 根据用户 ID 查找用户 - var user = await miniUserRepository.FindByIdAsync(descriptor.UserId, cancellationToken) - ?? throw new BusinessException(ErrorCodes.Unauthorized, "用户不存在"); - - // 3. 撤销旧刷新令牌(防止重复使用) - await refreshTokenStore.RevokeAsync(descriptor.Token, cancellationToken); - - // 4. 生成新的令牌对 - var profile = BuildProfile(user); - return await jwtTokenService.CreateTokensAsync(profile, false, cancellationToken); - } - - /// - /// 获取用户档案。 - /// - /// 用户 ID - /// 取消令牌 - /// 用户档案 - /// 用户不存在时抛出 - public async Task GetProfileAsync(long userId, CancellationToken cancellationToken = default) - { - var user = await miniUserRepository.FindByIdAsync(userId, cancellationToken) - ?? throw new BusinessException(ErrorCodes.NotFound, "用户不存在"); - - return BuildProfile(user); - } - - /// - /// 获取或绑定小程序用户:如果 OpenId 已存在则返回现有用户,否则创建新用户。 - /// - /// 微信 OpenId - /// 微信 UnionId(可选) - /// 昵称 - /// 头像地址(可选) - /// 租户 ID - /// 取消令牌 - /// 用户实体和是否为新用户的元组 - private async Task<(MiniUser user, bool isNew)> GetOrBindMiniUserAsync(string openId, string? unionId, string? nickname, string? avatar, long tenantId, CancellationToken cancellationToken) - { - // 检查用户是否已存在 - var existing = await miniUserRepository.FindByOpenIdAsync(openId, cancellationToken); - if (existing != null) - { - return (existing, false); - } - - // 创建新用户 - var created = await miniUserRepository.CreateOrUpdateAsync(openId, unionId, nickname, avatar, tenantId, cancellationToken); - return (created, true); - } - - private static CurrentUserProfile BuildProfile(MiniUser user) - => new() - { - UserId = user.Id, - Account = user.OpenId, - DisplayName = user.Nickname, - TenantId = user.TenantId, - MerchantId = null, - Roles = Array.Empty(), - Permissions = Array.Empty(), - Avatar = user.Avatar - }; - - private string BuildThrottleKey() - { - var ip = httpContextAccessor.HttpContext?.Connection.RemoteIpAddress ?? IPAddress.Loopback; - return $"mini-login:{ip}"; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Validators/BatchIdentityUserOperationCommandValidator.cs b/src/Application/TakeoutSaaS.Application/Identity/Validators/BatchIdentityUserOperationCommandValidator.cs deleted file mode 100644 index 675e213..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Validators/BatchIdentityUserOperationCommandValidator.cs +++ /dev/null @@ -1,24 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.Identity.Commands; - -namespace TakeoutSaaS.Application.Identity.Validators; - -/// -/// 批量用户操作命令验证器。 -/// -public sealed class BatchIdentityUserOperationCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public BatchIdentityUserOperationCommandValidator() - { - RuleFor(x => x.Operation).IsInEnum(); - RuleFor(x => x.UserIds).NotEmpty().Must(ids => ids.Length <= 100) - .WithMessage("单次最多只能选择 100 个用户"); - RuleForEach(x => x.UserIds) - .Must(value => long.TryParse(value, out _)) - .WithMessage("用户 ID 必须为有效的数字字符串"); - RuleFor(x => x.TenantId).GreaterThan(0).When(x => x.TenantId.HasValue); - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Validators/CreateIdentityUserCommandValidator.cs b/src/Application/TakeoutSaaS.Application/Identity/Validators/CreateIdentityUserCommandValidator.cs deleted file mode 100644 index 9c5451b..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Validators/CreateIdentityUserCommandValidator.cs +++ /dev/null @@ -1,37 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.Identity.Commands; - -namespace TakeoutSaaS.Application.Identity.Validators; - -/// -/// 创建用户命令验证器。 -/// -public sealed class CreateIdentityUserCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public CreateIdentityUserCommandValidator() - { - RuleFor(x => x.Account).NotEmpty().MaximumLength(64); - RuleFor(x => x.DisplayName).NotEmpty().MaximumLength(64); - RuleFor(x => x.Password).NotEmpty().Length(6, 32); - RuleFor(x => x.Avatar).MaximumLength(512); - RuleFor(x => x.TenantId).GreaterThan(0).When(x => x.TenantId.HasValue); - RuleForEach(x => x.RoleIds) - .Must(value => long.TryParse(value, out _)) - .WithMessage("角色 ID 必须为有效的数字字符串"); - When(x => !string.IsNullOrWhiteSpace(x.Phone), () => - { - RuleFor(x => x.Phone!) - .Matches("^1[3-9]\\d{9}$") - .WithMessage("手机号格式不正确"); - }); - When(x => !string.IsNullOrWhiteSpace(x.Email), () => - { - RuleFor(x => x.Email!) - .EmailAddress() - .WithMessage("邮箱格式不正确"); - }); - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Validators/SearchIdentityUsersQueryValidator.cs b/src/Application/TakeoutSaaS.Application/Identity/Validators/SearchIdentityUsersQueryValidator.cs deleted file mode 100644 index 409a51f..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Validators/SearchIdentityUsersQueryValidator.cs +++ /dev/null @@ -1,28 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.Identity.Queries; - -namespace TakeoutSaaS.Application.Identity.Validators; - -/// -/// 用户列表查询验证器。 -/// -public sealed class SearchIdentityUsersQueryValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public SearchIdentityUsersQueryValidator() - { - RuleFor(x => x.Page).GreaterThan(0); - RuleFor(x => x.PageSize).InclusiveBetween(1, 200); - RuleFor(x => x.Keyword).MaximumLength(128); - RuleFor(x => x.SortBy).MaximumLength(64); - RuleFor(x => x.TenantId).GreaterThan(0).When(x => x.TenantId.HasValue); - RuleFor(x => x.CreatedAtTo) - .GreaterThanOrEqualTo(x => x.CreatedAtFrom) - .When(x => x.CreatedAtFrom.HasValue && x.CreatedAtTo.HasValue); - RuleFor(x => x.LastLoginTo) - .GreaterThanOrEqualTo(x => x.LastLoginFrom) - .When(x => x.LastLoginFrom.HasValue && x.LastLoginTo.HasValue); - } -} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Validators/UpdateIdentityUserCommandValidator.cs b/src/Application/TakeoutSaaS.Application/Identity/Validators/UpdateIdentityUserCommandValidator.cs deleted file mode 100644 index 44ce8f1..0000000 --- a/src/Application/TakeoutSaaS.Application/Identity/Validators/UpdateIdentityUserCommandValidator.cs +++ /dev/null @@ -1,37 +0,0 @@ -using FluentValidation; -using TakeoutSaaS.Application.Identity.Commands; - -namespace TakeoutSaaS.Application.Identity.Validators; - -/// -/// 更新用户命令验证器。 -/// -public sealed class UpdateIdentityUserCommandValidator : AbstractValidator -{ - /// - /// 初始化验证规则。 - /// - public UpdateIdentityUserCommandValidator() - { - RuleFor(x => x.UserId).GreaterThan(0); - RuleFor(x => x.DisplayName).NotEmpty().MaximumLength(64); - RuleFor(x => x.Avatar).MaximumLength(512); - RuleFor(x => x.TenantId).GreaterThan(0).When(x => x.TenantId.HasValue); - RuleForEach(x => x.RoleIds) - .Must(value => long.TryParse(value, out _)) - .WithMessage("角色 ID 必须为有效的数字字符串") - .When(x => x.RoleIds != null); - When(x => !string.IsNullOrWhiteSpace(x.Phone), () => - { - RuleFor(x => x.Phone!) - .Matches("^1[3-9]\\d{9}$") - .WithMessage("手机号格式不正确"); - }); - When(x => !string.IsNullOrWhiteSpace(x.Email), () => - { - RuleFor(x => x.Email!) - .EmailAddress() - .WithMessage("邮箱格式不正确"); - }); - } -} diff --git a/src/Application/TakeoutSaaS.Application/Messaging/Abstractions/IEventPublisher.cs b/src/Application/TakeoutSaaS.Application/Messaging/Abstractions/IEventPublisher.cs deleted file mode 100644 index c17a6f7..0000000 --- a/src/Application/TakeoutSaaS.Application/Messaging/Abstractions/IEventPublisher.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace TakeoutSaaS.Application.Messaging.Abstractions; - -/// -/// 领域事件发布抽象。 -/// -public interface IEventPublisher -{ - /// - /// 发布领域事件。 - /// - Task PublishAsync(string routingKey, TEvent @event, CancellationToken cancellationToken = default); -} diff --git a/src/Application/TakeoutSaaS.Application/Messaging/EventRoutingKeys.cs b/src/Application/TakeoutSaaS.Application/Messaging/EventRoutingKeys.cs deleted file mode 100644 index c161ef3..0000000 --- a/src/Application/TakeoutSaaS.Application/Messaging/EventRoutingKeys.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace TakeoutSaaS.Application.Messaging; - -/// -/// 事件路由键常量。 -/// -public static class EventRoutingKeys -{ - /// - /// 订单创建事件路由键。 - /// - public const string OrderCreated = "orders.created"; - - /// - /// 支付成功事件路由键。 - /// - public const string PaymentSucceeded = "payments.succeeded"; -} diff --git a/src/Application/TakeoutSaaS.Application/Messaging/Events/OrderCreatedEvent.cs b/src/Application/TakeoutSaaS.Application/Messaging/Events/OrderCreatedEvent.cs deleted file mode 100644 index 2a84f05..0000000 --- a/src/Application/TakeoutSaaS.Application/Messaging/Events/OrderCreatedEvent.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace TakeoutSaaS.Application.Messaging.Events; - -/// -/// 订单创建事件。 -/// -public sealed class OrderCreatedEvent -{ - /// - /// 订单标识。 - /// - public long OrderId { get; init; } - - /// - /// 订单编号。 - /// - public string OrderNo { get; init; } = string.Empty; - - /// - /// 实付金额。 - /// - public decimal Amount { get; init; } - - /// - /// 所属租户。 - /// - public long TenantId { get; init; } - - /// - /// 创建时间(UTC)。 - /// - public DateTime CreatedAt { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/Messaging/Events/PaymentSucceededEvent.cs b/src/Application/TakeoutSaaS.Application/Messaging/Events/PaymentSucceededEvent.cs deleted file mode 100644 index b0094f7..0000000 --- a/src/Application/TakeoutSaaS.Application/Messaging/Events/PaymentSucceededEvent.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace TakeoutSaaS.Application.Messaging.Events; - -/// -/// 支付成功事件。 -/// -public sealed class PaymentSucceededEvent -{ - /// - /// 订单标识。 - /// - public long OrderId { get; init; } - - /// - /// 支付流水号。 - /// - public string PaymentNo { get; init; } = string.Empty; - - /// - /// 支付金额。 - /// - public decimal Amount { get; init; } - - /// - /// 所属租户。 - /// - public long TenantId { get; init; } - - /// - /// 支付时间(UTC)。 - /// - public DateTime PaidAt { get; init; } -} diff --git a/src/Application/TakeoutSaaS.Application/Messaging/Extensions/MessagingServiceCollectionExtensions.cs b/src/Application/TakeoutSaaS.Application/Messaging/Extensions/MessagingServiceCollectionExtensions.cs deleted file mode 100644 index 82e9614..0000000 --- a/src/Application/TakeoutSaaS.Application/Messaging/Extensions/MessagingServiceCollectionExtensions.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using TakeoutSaaS.Application.Messaging.Abstractions; -using TakeoutSaaS.Application.Messaging.Services; - -namespace TakeoutSaaS.Application.Messaging.Extensions; - -/// -/// 消息模块应用层注册。 -/// -public static class MessagingServiceCollectionExtensions -{ - /// - /// 注册事件发布器。 - /// - public static IServiceCollection AddMessagingApplication(this IServiceCollection services) - { - services.AddScoped(); - return services; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Messaging/Services/EventPublisher.cs b/src/Application/TakeoutSaaS.Application/Messaging/Services/EventPublisher.cs deleted file mode 100644 index d87dc80..0000000 --- a/src/Application/TakeoutSaaS.Application/Messaging/Services/EventPublisher.cs +++ /dev/null @@ -1,14 +0,0 @@ -using TakeoutSaaS.Application.Messaging.Abstractions; -using TakeoutSaaS.Module.Messaging.Abstractions; - -namespace TakeoutSaaS.Application.Messaging.Services; - -/// -/// 事件发布适配器,封装应用层到 MQ 的发布。 -/// -public sealed class EventPublisher(IMessagePublisher messagePublisher) : IEventPublisher -{ - /// - public Task PublishAsync(string routingKey, TEvent @event, CancellationToken cancellationToken = default) - => messagePublisher.PublishAsync(routingKey, @event, cancellationToken); -} diff --git a/src/Application/TakeoutSaaS.Application/Sms/Abstractions/IVerificationCodeService.cs b/src/Application/TakeoutSaaS.Application/Sms/Abstractions/IVerificationCodeService.cs deleted file mode 100644 index 4eab7cc..0000000 --- a/src/Application/TakeoutSaaS.Application/Sms/Abstractions/IVerificationCodeService.cs +++ /dev/null @@ -1,19 +0,0 @@ -using TakeoutSaaS.Application.Sms.Contracts; - -namespace TakeoutSaaS.Application.Sms.Abstractions; - -/// -/// 短信验证码服务抽象。 -/// -public interface IVerificationCodeService -{ - /// - /// 发送验证码。 - /// - Task SendAsync(SendVerificationCodeRequest request, CancellationToken cancellationToken = default); - - /// - /// 校验验证码。 - /// - Task VerifyAsync(VerifyVerificationCodeRequest request, CancellationToken cancellationToken = default); -} diff --git a/src/Application/TakeoutSaaS.Application/Sms/Contracts/SendVerificationCodeRequest.cs b/src/Application/TakeoutSaaS.Application/Sms/Contracts/SendVerificationCodeRequest.cs deleted file mode 100644 index 5a1bca6..0000000 --- a/src/Application/TakeoutSaaS.Application/Sms/Contracts/SendVerificationCodeRequest.cs +++ /dev/null @@ -1,27 +0,0 @@ -using TakeoutSaaS.Module.Sms; - -namespace TakeoutSaaS.Application.Sms.Contracts; - -/// -/// 发送验证码请求。 -/// -/// -/// 创建发送请求。 -/// -public sealed class SendVerificationCodeRequest(string phoneNumber, string scene, SmsProviderKind? provider = null) -{ - /// - /// 手机号(支持 +86 前缀或纯 11 位)。 - /// - public string PhoneNumber { get; } = phoneNumber; - - /// - /// 业务场景(如 login/register/reset)。 - /// - public string Scene { get; } = scene; - - /// - /// 指定服务商,未指定则使用默认配置。 - /// - public SmsProviderKind? Provider { get; } = provider; -} diff --git a/src/Application/TakeoutSaaS.Application/Sms/Contracts/SendVerificationCodeResponse.cs b/src/Application/TakeoutSaaS.Application/Sms/Contracts/SendVerificationCodeResponse.cs deleted file mode 100644 index e9f84f1..0000000 --- a/src/Application/TakeoutSaaS.Application/Sms/Contracts/SendVerificationCodeResponse.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace TakeoutSaaS.Application.Sms.Contracts; - -/// -/// 发送验证码响应。 -/// -public sealed class SendVerificationCodeResponse -{ - /// - /// 过期时间。 - /// - public DateTimeOffset ExpiresAt { get; set; } - - /// - /// 请求标识。 - /// - public string? RequestId { get; set; } -} diff --git a/src/Application/TakeoutSaaS.Application/Sms/Contracts/VerifyVerificationCodeRequest.cs b/src/Application/TakeoutSaaS.Application/Sms/Contracts/VerifyVerificationCodeRequest.cs deleted file mode 100644 index 9eb1262..0000000 --- a/src/Application/TakeoutSaaS.Application/Sms/Contracts/VerifyVerificationCodeRequest.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace TakeoutSaaS.Application.Sms.Contracts; - -/// -/// 校验验证码请求。 -/// -/// -/// 创建校验请求。 -/// -public sealed class VerifyVerificationCodeRequest(string phoneNumber, string scene, string code) -{ - /// - /// 手机号。 - /// - public string PhoneNumber { get; } = phoneNumber; - - /// - /// 业务场景。 - /// - public string Scene { get; } = scene; - - /// - /// 填写的验证码。 - /// - public string Code { get; } = code; -} diff --git a/src/Application/TakeoutSaaS.Application/Sms/Extensions/SmsServiceCollectionExtensions.cs b/src/Application/TakeoutSaaS.Application/Sms/Extensions/SmsServiceCollectionExtensions.cs deleted file mode 100644 index 5a4d7c7..0000000 --- a/src/Application/TakeoutSaaS.Application/Sms/Extensions/SmsServiceCollectionExtensions.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using TakeoutSaaS.Application.Sms.Abstractions; -using TakeoutSaaS.Application.Sms.Options; -using TakeoutSaaS.Application.Sms.Services; - -namespace TakeoutSaaS.Application.Sms.Extensions; - -/// -/// 短信应用服务注册扩展。 -/// -public static class SmsServiceCollectionExtensions -{ - /// - /// 注册短信验证码应用服务。 - /// - public static IServiceCollection AddSmsApplication(this IServiceCollection services, IConfiguration configuration) - { - services.AddOptions() - .Bind(configuration.GetSection("Sms:VerificationCode")) - .ValidateDataAnnotations() - .ValidateOnStart(); - - services.AddScoped(); - return services; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Sms/Options/VerificationCodeOptions.cs b/src/Application/TakeoutSaaS.Application/Sms/Options/VerificationCodeOptions.cs deleted file mode 100644 index fd49271..0000000 --- a/src/Application/TakeoutSaaS.Application/Sms/Options/VerificationCodeOptions.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Application.Sms.Options; - -/// -/// 验证码发送配置。 -/// -public sealed class VerificationCodeOptions -{ - /// - /// 验证码位数,默认 6。 - /// - [Range(4, 10)] - public int CodeLength { get; set; } = 6; - - /// - /// 过期时间(分钟)。 - /// - [Range(1, 60)] - public int ExpireMinutes { get; set; } = 5; - - /// - /// 发送冷却时间(秒),用于防止频繁请求。 - /// - [Range(10, 300)] - public int CooldownSeconds { get; set; } = 60; - - /// - /// 缓存前缀。 - /// - [Required] - public string CachePrefix { get; set; } = "sms:code"; -} diff --git a/src/Application/TakeoutSaaS.Application/Sms/Services/VerificationCodeService.cs b/src/Application/TakeoutSaaS.Application/Sms/Services/VerificationCodeService.cs deleted file mode 100644 index 1fbac0f..0000000 --- a/src/Application/TakeoutSaaS.Application/Sms/Services/VerificationCodeService.cs +++ /dev/null @@ -1,155 +0,0 @@ -using Microsoft.Extensions.Caching.Distributed; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using System.Security.Cryptography; -using System.Text; -using TakeoutSaaS.Application.Sms.Abstractions; -using TakeoutSaaS.Application.Sms.Contracts; -using TakeoutSaaS.Application.Sms.Options; -using TakeoutSaaS.Module.Sms.Abstractions; -using TakeoutSaaS.Module.Sms.Models; -using TakeoutSaaS.Module.Sms.Options; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Sms.Services; - -/// -/// 短信验证码服务实现。 -/// -public sealed class VerificationCodeService( - ISmsSenderResolver senderResolver, - IOptionsMonitor smsOptionsMonitor, - IOptionsMonitor codeOptionsMonitor, - ITenantProvider tenantProvider, - IDistributedCache cache, - ILogger logger) : IVerificationCodeService -{ - /// - public async Task SendAsync(SendVerificationCodeRequest request, CancellationToken cancellationToken = default) - { - // 1. 参数校验 - if (string.IsNullOrWhiteSpace(request.PhoneNumber)) - { - throw new BusinessException(ErrorCodes.BadRequest, "手机号不能为空"); - } - - if (string.IsNullOrWhiteSpace(request.Scene)) - { - throw new BusinessException(ErrorCodes.BadRequest, "场景不能为空"); - } - - // 2. 解析模板与缓存键 - var smsOptions = smsOptionsMonitor.CurrentValue; - var codeOptions = codeOptionsMonitor.CurrentValue; - var templateCode = ResolveTemplate(request.Scene, smsOptions); - var phone = NormalizePhoneNumber(request.PhoneNumber); - var tenantKey = tenantProvider.GetCurrentTenantId() == 0 ? "platform" : tenantProvider.GetCurrentTenantId().ToString(); - var cacheKey = $"{codeOptions.CachePrefix}:{tenantKey}:{request.Scene}:{phone}"; - var cooldownKey = $"{cacheKey}:cooldown"; - - // 3. 检查冷却期 - await EnsureCooldownAsync(cooldownKey, codeOptions.CooldownSeconds, cancellationToken).ConfigureAwait(false); - - // 4. 生成验证码并发送短信 - var code = GenerateCode(codeOptions.CodeLength); - var variables = new Dictionary { { "code", code } }; - var sender = senderResolver.Resolve(request.Provider); - - var smsRequest = new SmsSendRequest(phone, templateCode, variables, smsOptions.DefaultSignName); - var smsResult = await sender.SendAsync(smsRequest, cancellationToken).ConfigureAwait(false); - if (!smsResult.Success) - { - throw new BusinessException(ErrorCodes.InternalServerError, $"短信发送失败:{smsResult.Message}"); - } - - // 5. 写入验证码与冷却缓存 - var expiresAt = DateTimeOffset.UtcNow.AddMinutes(codeOptions.ExpireMinutes); - await cache.SetStringAsync(cacheKey, code, new DistributedCacheEntryOptions - { - AbsoluteExpiration = expiresAt - }, cancellationToken).ConfigureAwait(false); - - await cache.SetStringAsync(cooldownKey, "1", new DistributedCacheEntryOptions - { - AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(codeOptions.CooldownSeconds) - }, cancellationToken).ConfigureAwait(false); - - logger.LogInformation("发送验证码成功,Phone:{Phone} Scene:{Scene} Tenant:{Tenant}", phone, request.Scene, tenantKey); - return new SendVerificationCodeResponse - { - ExpiresAt = expiresAt, - RequestId = smsResult.RequestId - }; - } - - /// - public async Task VerifyAsync(VerifyVerificationCodeRequest request, CancellationToken cancellationToken = default) - { - // 1. 基础校验 - if (string.IsNullOrWhiteSpace(request.Code)) - { - return false; - } - - // 2. 读取验证码 - var codeOptions = codeOptionsMonitor.CurrentValue; - var phone = NormalizePhoneNumber(request.PhoneNumber); - var tenantKey = tenantProvider.GetCurrentTenantId() == 0 ? "platform" : tenantProvider.GetCurrentTenantId().ToString(); - var cacheKey = $"{codeOptions.CachePrefix}:{tenantKey}:{request.Scene}:{phone}"; - - var cachedCode = await cache.GetStringAsync(cacheKey, cancellationToken).ConfigureAwait(false); - if (string.IsNullOrWhiteSpace(cachedCode)) - { - return false; - } - - // 3. 比对成功后清除缓存 - var success = string.Equals(cachedCode, request.Code, StringComparison.Ordinal); - if (success) - { - await cache.RemoveAsync(cacheKey, cancellationToken).ConfigureAwait(false); - } - - return success; - } - - private static string ResolveTemplate(string scene, SmsOptions options) - { - if (options.SceneTemplates.TryGetValue(scene, out var template) && !string.IsNullOrWhiteSpace(template)) - { - return template; - } - - throw new BusinessException(ErrorCodes.BadRequest, $"未配置场景 {scene} 的短信模板"); - } - - private static string NormalizePhoneNumber(string phone) - { - var trimmed = phone.Trim(); - return trimmed.StartsWith("+", StringComparison.Ordinal) ? trimmed : $"+86{trimmed}"; - } - - private static string GenerateCode(int length) - { - var buffer = new byte[length]; - RandomNumberGenerator.Fill(buffer); - var builder = new StringBuilder(length); - foreach (var b in buffer) - { - builder.Append((b % 10).ToString()); - } - - return builder.ToString()[..length]; - } - - private async Task EnsureCooldownAsync(string cooldownKey, int cooldownSeconds, CancellationToken cancellationToken) - { - var existing = await cache.GetStringAsync(cooldownKey, cancellationToken).ConfigureAwait(false); - if (!string.IsNullOrEmpty(existing)) - { - throw new BusinessException(ErrorCodes.BadRequest, "请求过于频繁,请稍后再试"); - } - } -} diff --git a/src/Application/TakeoutSaaS.Application/Storage/Abstractions/IFileStorageService.cs b/src/Application/TakeoutSaaS.Application/Storage/Abstractions/IFileStorageService.cs deleted file mode 100644 index b92f66d..0000000 --- a/src/Application/TakeoutSaaS.Application/Storage/Abstractions/IFileStorageService.cs +++ /dev/null @@ -1,19 +0,0 @@ -using TakeoutSaaS.Application.Storage.Contracts; - -namespace TakeoutSaaS.Application.Storage.Abstractions; - -/// -/// 文件存储应用服务抽象。 -/// -public interface IFileStorageService -{ - /// - /// 通过服务端中转上传文件。 - /// - Task UploadAsync(UploadFileRequest request, CancellationToken cancellationToken = default); - - /// - /// 生成前端直传凭证(预签名上传)。 - /// - Task CreateDirectUploadAsync(DirectUploadRequest request, CancellationToken cancellationToken = default); -} diff --git a/src/Application/TakeoutSaaS.Application/Storage/Contracts/DirectUploadRequest.cs b/src/Application/TakeoutSaaS.Application/Storage/Contracts/DirectUploadRequest.cs deleted file mode 100644 index 48e05eb..0000000 --- a/src/Application/TakeoutSaaS.Application/Storage/Contracts/DirectUploadRequest.cs +++ /dev/null @@ -1,37 +0,0 @@ -using TakeoutSaaS.Application.Storage.Enums; - -namespace TakeoutSaaS.Application.Storage.Contracts; - -/// -/// 直传凭证请求模型。 -/// -/// -/// 创建直传请求。 -/// -public sealed class DirectUploadRequest(UploadFileType fileType, string fileName, string contentType, long contentLength, string? requestOrigin) -{ - /// - /// 文件类型。 - /// - public UploadFileType FileType { get; } = fileType; - - /// - /// 文件名。 - /// - public string FileName { get; } = fileName; - - /// - /// 内容类型。 - /// - public string ContentType { get; } = contentType; - - /// - /// 文件长度。 - /// - public long ContentLength { get; } = contentLength; - - /// - /// 请求来源(Origin/Referer)。 - /// - public string? RequestOrigin { get; } = requestOrigin; -} diff --git a/src/Application/TakeoutSaaS.Application/Storage/Contracts/DirectUploadResponse.cs b/src/Application/TakeoutSaaS.Application/Storage/Contracts/DirectUploadResponse.cs deleted file mode 100644 index de1ab0b..0000000 --- a/src/Application/TakeoutSaaS.Application/Storage/Contracts/DirectUploadResponse.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace TakeoutSaaS.Application.Storage.Contracts; - -/// -/// 直传凭证响应模型。 -/// -public sealed class DirectUploadResponse -{ - /// - /// 预签名上传地址。 - /// - public string UploadUrl { get; set; } = string.Empty; - - /// - /// 表单直传所需字段(PUT 直传为空)。 - /// - public IReadOnlyDictionary FormFields { get; set; } = new Dictionary(); - - /// - /// 预签名过期时间。 - /// - public DateTimeOffset ExpiresAt { get; set; } - - /// - /// 对象键。 - /// - public string ObjectKey { get; set; } = string.Empty; - - /// - /// 直传完成后的访问链接(包含签名)。 - /// - public string? DownloadUrl { get; set; } -} diff --git a/src/Application/TakeoutSaaS.Application/Storage/Contracts/FileUploadResponse.cs b/src/Application/TakeoutSaaS.Application/Storage/Contracts/FileUploadResponse.cs deleted file mode 100644 index 3f12168..0000000 --- a/src/Application/TakeoutSaaS.Application/Storage/Contracts/FileUploadResponse.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace TakeoutSaaS.Application.Storage.Contracts; - -/// -/// 上传完成后的返回模型。 -/// -public sealed class FileUploadResponse -{ - /// - /// 访问 URL(已包含签名)。 - /// - public string Url { get; set; } = string.Empty; - - /// - /// 文件名。 - /// - public string FileName { get; set; } = string.Empty; - - /// - /// 文件大小。 - /// - public long FileSize { get; set; } -} diff --git a/src/Application/TakeoutSaaS.Application/Storage/Contracts/UploadFileRequest.cs b/src/Application/TakeoutSaaS.Application/Storage/Contracts/UploadFileRequest.cs deleted file mode 100644 index 43e12f2..0000000 --- a/src/Application/TakeoutSaaS.Application/Storage/Contracts/UploadFileRequest.cs +++ /dev/null @@ -1,48 +0,0 @@ -using TakeoutSaaS.Application.Storage.Enums; - -namespace TakeoutSaaS.Application.Storage.Contracts; - -/// -/// 上传文件请求模型。 -/// -/// -/// 创建上传文件请求。 -/// -public sealed class UploadFileRequest( - UploadFileType fileType, - Stream content, - string fileName, - string contentType, - long contentLength, - string? requestOrigin) -{ - /// - /// 文件分类。 - /// - public UploadFileType FileType { get; } = fileType; - - /// - /// 文件流。 - /// - public Stream Content { get; } = content; - - /// - /// 原始文件名。 - /// - public string FileName { get; } = fileName; - - /// - /// 内容类型。 - /// - public string ContentType { get; } = contentType; - - /// - /// 文件大小。 - /// - public long ContentLength { get; } = contentLength; - - /// - /// 请求来源(Origin/Referer)。 - /// - public string? RequestOrigin { get; } = requestOrigin; -} diff --git a/src/Application/TakeoutSaaS.Application/Storage/Enums/UploadFileType.cs b/src/Application/TakeoutSaaS.Application/Storage/Enums/UploadFileType.cs deleted file mode 100644 index 4839bf5..0000000 --- a/src/Application/TakeoutSaaS.Application/Storage/Enums/UploadFileType.cs +++ /dev/null @@ -1,37 +0,0 @@ -namespace TakeoutSaaS.Application.Storage.Enums; - -/// -/// 上传文件类型,映射业务场景。 -/// -public enum UploadFileType -{ - /// - /// 菜品图片。 - /// - DishImage = 1, - - /// - /// 商户 Logo。 - /// - MerchantLogo = 2, - - /// - /// 用户头像。 - /// - UserAvatar = 3, - - /// - /// 评价图片。 - /// - ReviewImage = 4, - - /// - /// 入住资质文件。 - /// - BusinessLicense = 5, - - /// - /// 其他通用文件。 - /// - Other = 9 -} diff --git a/src/Application/TakeoutSaaS.Application/Storage/Extensions/StorageServiceCollectionExtensions.cs b/src/Application/TakeoutSaaS.Application/Storage/Extensions/StorageServiceCollectionExtensions.cs deleted file mode 100644 index 1301804..0000000 --- a/src/Application/TakeoutSaaS.Application/Storage/Extensions/StorageServiceCollectionExtensions.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using TakeoutSaaS.Application.Storage.Abstractions; -using TakeoutSaaS.Application.Storage.Services; - -namespace TakeoutSaaS.Application.Storage.Extensions; - -/// -/// 存储应用服务注册扩展。 -/// -public static class StorageServiceCollectionExtensions -{ - /// - /// 注册文件存储应用服务。 - /// - public static IServiceCollection AddStorageApplication(this IServiceCollection services) - { - services.AddScoped(); - return services; - } -} diff --git a/src/Application/TakeoutSaaS.Application/Storage/Extensions/UploadFileTypeParser.cs b/src/Application/TakeoutSaaS.Application/Storage/Extensions/UploadFileTypeParser.cs deleted file mode 100644 index a4afe1d..0000000 --- a/src/Application/TakeoutSaaS.Application/Storage/Extensions/UploadFileTypeParser.cs +++ /dev/null @@ -1,46 +0,0 @@ -using TakeoutSaaS.Application.Storage.Enums; - -namespace TakeoutSaaS.Application.Storage.Extensions; - -/// -/// 上传类型解析与辅助方法。 -/// -public static class UploadFileTypeParser -{ - /// - /// 将字符串解析为上传类型。 - /// - public static bool TryParse(string? value, out UploadFileType type) - { - type = UploadFileType.Other; - if (string.IsNullOrWhiteSpace(value)) - { - return false; - } - - var normalized = value.Trim().ToLowerInvariant(); - type = normalized switch - { - "dish_image" => UploadFileType.DishImage, - "merchant_logo" => UploadFileType.MerchantLogo, - "user_avatar" => UploadFileType.UserAvatar, - "review_image" => UploadFileType.ReviewImage, - "business_license" => UploadFileType.BusinessLicense, - _ => UploadFileType.Other - }; - - return type != UploadFileType.Other || normalized == "other"; - } - - /// - /// 将上传类型转换为路径片段。 - /// - public static string ToFolderName(this UploadFileType type) => type switch - { - UploadFileType.DishImage => "dishes", - UploadFileType.MerchantLogo => "merchants", - UploadFileType.UserAvatar => "users", - UploadFileType.ReviewImage => "reviews", - _ => "files" - }; -} diff --git a/src/Application/TakeoutSaaS.Application/Storage/Services/FileStorageService.cs b/src/Application/TakeoutSaaS.Application/Storage/Services/FileStorageService.cs deleted file mode 100644 index 17eb087..0000000 --- a/src/Application/TakeoutSaaS.Application/Storage/Services/FileStorageService.cs +++ /dev/null @@ -1,282 +0,0 @@ -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using System.Security.Cryptography; -using System.Text; -using TakeoutSaaS.Application.Storage.Abstractions; -using TakeoutSaaS.Application.Storage.Contracts; -using TakeoutSaaS.Application.Storage.Enums; -using TakeoutSaaS.Application.Storage.Extensions; -using TakeoutSaaS.Module.Storage.Abstractions; -using TakeoutSaaS.Module.Storage.Models; -using TakeoutSaaS.Module.Storage.Options; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Application.Storage.Services; - -/// -/// 文件存储应用服务,实现上传与直传凭证生成。 -/// -public sealed class FileStorageService( - IStorageProviderResolver providerResolver, - IOptionsMonitor optionsMonitor, - ITenantProvider tenantProvider, - ICurrentUserAccessor currentUserAccessor, - ILogger logger) : IFileStorageService -{ - /// - public async Task UploadAsync(UploadFileRequest request, CancellationToken cancellationToken = default) - { - // 1. 校验请求 - if (request is null) - { - throw new BusinessException(ErrorCodes.BadRequest, "上传请求不能为空"); - } - - // 2. 读取安全配置并校验来源/大小/类型 - var options = optionsMonitor.CurrentValue; - var security = options.Security; - ValidateOrigin(request.RequestOrigin, security); - ValidateFileSize(request.ContentLength, security); - - var extension = NormalizeExtension(request.FileName); - ValidateExtension(request.FileType, extension, security); - var contentType = NormalizeContentType(request.ContentType, extension); - ResetStream(request.Content); - - // 3. 生成对象键与元数据 - var objectKey = BuildObjectKey(request.FileType, extension); - var metadata = BuildMetadata(request.FileType); - var expires = TimeSpan.FromMinutes(Math.Max(1, security.DefaultUrlExpirationMinutes)); - var provider = providerResolver.Resolve(); - - // 4. 上传到对象存储 - var uploadResult = await provider.UploadAsync( - new StorageUploadRequest(objectKey, request.Content, contentType, request.ContentLength, false, expires, metadata), - cancellationToken).ConfigureAwait(false); - - // 5. 构造公开访问链接并返回 - var finalUrl = provider.BuildPublicUrl(uploadResult.ObjectKey); - logger.LogInformation("文件上传成功:{ObjectKey} ({Size} bytes)", objectKey, request.ContentLength); - - return new FileUploadResponse - { - Url = finalUrl, - FileName = Path.GetFileName(uploadResult.ObjectKey), - FileSize = uploadResult.FileSize - }; - } - - /// - public async Task CreateDirectUploadAsync(DirectUploadRequest request, CancellationToken cancellationToken = default) - { - // 1. 校验请求 - if (request is null) - { - throw new BusinessException(ErrorCodes.BadRequest, "直传请求不能为空"); - } - - // 2. 校验来源/大小/类型 - var options = optionsMonitor.CurrentValue; - var security = options.Security; - ValidateOrigin(request.RequestOrigin, security); - ValidateFileSize(request.ContentLength, security); - - var extension = NormalizeExtension(request.FileName); - ValidateExtension(request.FileType, extension, security); - var contentType = NormalizeContentType(request.ContentType, extension); - - // 3. 构建直传参数 - var objectKey = BuildObjectKey(request.FileType, extension); - var provider = providerResolver.Resolve(); - var expires = TimeSpan.FromMinutes(Math.Max(1, security.DefaultUrlExpirationMinutes)); - - // 4. 向存储获取直传凭证 - var directResult = await provider.CreateDirectUploadAsync( - new StorageDirectUploadRequest(objectKey, contentType, request.ContentLength, expires), - cancellationToken).ConfigureAwait(false); - - // 5. 构造直传结果并追加防盗链 - var finalDownloadUrl = directResult.SignedDownloadUrl != null - ? AppendAntiLeechToken(directResult.SignedDownloadUrl, objectKey, expires, security) - : null; - - return new DirectUploadResponse - { - UploadUrl = directResult.UploadUrl, - FormFields = directResult.FormFields, - ExpiresAt = directResult.ExpiresAt, - ObjectKey = directResult.ObjectKey, - DownloadUrl = finalDownloadUrl - }; - } - - /// - /// 校验文件大小。 - /// - private static void ValidateFileSize(long size, StorageSecurityOptions security) - { - if (size <= 0) - { - throw new BusinessException(ErrorCodes.BadRequest, "文件内容为空"); - } - - if (size > security.MaxFileSizeBytes) - { - throw new BusinessException(ErrorCodes.BadRequest, $"文件过大,最大允许 {security.MaxFileSizeBytes / 1024 / 1024}MB"); - } - } - - /// - /// 校验文件后缀是否符合配置。 - /// - private static void ValidateExtension(UploadFileType type, string extension, StorageSecurityOptions security) - { - var allowedImages = security.AllowedImageExtensions ?? Array.Empty(); - var allowedFiles = security.AllowedFileExtensions ?? Array.Empty(); - - if (type is UploadFileType.DishImage or UploadFileType.MerchantLogo or UploadFileType.UserAvatar or UploadFileType.ReviewImage) - { - if (!allowedImages.Contains(extension, StringComparer.OrdinalIgnoreCase)) - { - throw new BusinessException(ErrorCodes.BadRequest, $"不支持的图片格式:{extension}"); - } - } - else if (!allowedFiles.Contains(extension, StringComparer.OrdinalIgnoreCase)) - { - throw new BusinessException(ErrorCodes.BadRequest, $"不支持的文件格式:{extension}"); - } - } - - /// - /// 统一化文件后缀(小写,默认 .bin)。 - /// - private static string NormalizeExtension(string fileName) - { - var extension = Path.GetExtension(fileName); - if (string.IsNullOrWhiteSpace(extension)) - { - return ".bin"; - } - - return extension.ToLowerInvariant(); - } - - /// - /// 根据内容类型或后缀推断 Content-Type。 - /// - private static string NormalizeContentType(string contentType, string extension) - { - if (!string.IsNullOrWhiteSpace(contentType)) - { - return contentType; - } - - return extension switch - { - ".jpg" or ".jpeg" => "image/jpeg", - ".png" => "image/png", - ".gif" => "image/gif", - ".webp" => "image/webp", - ".pdf" => "application/pdf", - _ => "application/octet-stream" - }; - } - - /// - /// 校验请求来源是否在白名单内。 - /// - private void ValidateOrigin(string? origin, StorageSecurityOptions security) - { - if (!security.EnableRefererValidation || security.AllowedReferers.Length == 0) - { - return; - } - - if (string.IsNullOrWhiteSpace(origin)) - { - throw new BusinessException(ErrorCodes.Forbidden, "未授权的访问来源"); - } - - var isAllowed = security.AllowedReferers.Any(allowed => - !string.IsNullOrWhiteSpace(allowed) && - origin.StartsWith(allowed, StringComparison.OrdinalIgnoreCase)); - - if (!isAllowed) - { - throw new BusinessException(ErrorCodes.Forbidden, "访问来源未在白名单中"); - } - } - - /// - /// 生成对象存储的键路径。 - /// - private string BuildObjectKey(UploadFileType type, string extension) - { - var tenantId = tenantProvider.GetCurrentTenantId(); - var tenantSegment = tenantId == 0 ? "platform" : tenantId.ToString(); - var folder = type.ToFolderName(); - var now = DateTime.UtcNow; - var fileName = $"{Guid.NewGuid():N}{extension}"; - - return $"{tenantSegment}/{folder}/{now:yyyy/MM/dd}/{fileName}"; - } - - /// - /// 组装对象元数据,便于追踪租户与用户。 - /// - private IDictionary BuildMetadata(UploadFileType type) - { - var metadata = new Dictionary - { - ["x-meta-upload-type"] = type.ToString(), - ["x-meta-tenant-id"] = tenantProvider.GetCurrentTenantId().ToString() - }; - - if (currentUserAccessor.IsAuthenticated) - { - metadata["x-meta-user-id"] = currentUserAccessor.UserId.ToString(); - } - - return metadata; - } - - /// - /// 重置文件流的读取位置。 - /// - private static void ResetStream(Stream stream) - { - if (stream.CanSeek) - { - stream.Position = 0; - } - } - - /// - /// 为访问链接追加防盗链签名(可配合 CDN Token 验证)。 - /// - private static string AppendAntiLeechToken(string url, string objectKey, TimeSpan expires, StorageSecurityOptions security) - { - if (string.IsNullOrWhiteSpace(security.AntiLeechTokenSecret)) - { - return url; - } - - // 若链接已包含云厂商签名参数,则避免追加自定义参数导致验签失败。 - if (url.Contains("X-Amz-Signature", StringComparison.OrdinalIgnoreCase) || - url.Contains("q-sign-algorithm", StringComparison.OrdinalIgnoreCase) || - url.Contains("Signature=", StringComparison.OrdinalIgnoreCase)) - { - return url; - } - - var expireAt = DateTimeOffset.UtcNow.Add(expires).ToUnixTimeSeconds(); - var payload = $"{objectKey}:{expireAt}:{security.AntiLeechTokenSecret}"; - var hashBytes = SHA256.HashData(Encoding.UTF8.GetBytes(payload)); - var token = Convert.ToHexString(hashBytes).ToLowerInvariant(); - var separator = url.Contains('?', StringComparison.Ordinal) ? "&" : "?"; - return $"{url}{separator}ts={expireAt}&token={token}"; - } -} diff --git a/src/Domain/TakeoutSaaS.Domain/Deliveries/Repositories/IDeliveryRepository.cs b/src/Domain/TakeoutSaaS.Domain/Deliveries/Repositories/IDeliveryRepository.cs deleted file mode 100644 index f97f67e..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Deliveries/Repositories/IDeliveryRepository.cs +++ /dev/null @@ -1,87 +0,0 @@ -using TakeoutSaaS.Domain.Deliveries.Entities; -using TakeoutSaaS.Domain.Deliveries.Enums; - -namespace TakeoutSaaS.Domain.Deliveries.Repositories; - -/// -/// 配送聚合仓储契约。 -/// -public interface IDeliveryRepository -{ - /// - /// 依据标识获取配送单。 - /// - /// 配送单 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 配送单实体或 null。 - Task FindByIdAsync(long deliveryOrderId, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 依据订单标识获取配送单。 - /// - /// 订单 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 配送单实体或 null。 - Task FindByOrderIdAsync(long orderId, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 获取配送事件轨迹。 - /// - /// 配送单 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 配送事件列表。 - Task> GetEventsAsync(long deliveryOrderId, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 新增配送单。 - /// - /// 配送单实体。 - /// 取消标记。 - /// 异步任务。 - Task AddDeliveryOrderAsync(DeliveryOrder deliveryOrder, CancellationToken cancellationToken = default); - - /// - /// 新增配送事件。 - /// - /// 配送事件。 - /// 取消标记。 - /// 异步任务。 - Task AddEventAsync(DeliveryEvent deliveryEvent, CancellationToken cancellationToken = default); - - /// - /// 持久化变更。 - /// - /// 取消标记。 - /// 异步任务。 - Task SaveChangesAsync(CancellationToken cancellationToken = default); - - /// - /// 按状态查询配送单。 - /// - /// 租户 ID。 - /// 配送状态。 - /// 订单 ID。 - /// 取消标记。 - /// 配送单列表。 - Task> SearchAsync(long tenantId, DeliveryStatus? status, long? orderId, CancellationToken cancellationToken = default); - - /// - /// 更新配送单。 - /// - /// 配送单实体。 - /// 取消标记。 - /// 异步任务。 - Task UpdateDeliveryOrderAsync(DeliveryOrder deliveryOrder, CancellationToken cancellationToken = default); - - /// - /// 删除配送单及事件。 - /// - /// 配送单 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 异步任务。 - Task DeleteDeliveryOrderAsync(long deliveryOrderId, long tenantId, CancellationToken cancellationToken = default); -} diff --git a/src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/ICacheInvalidationLogRepository.cs b/src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/ICacheInvalidationLogRepository.cs deleted file mode 100644 index 90f8f12..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/ICacheInvalidationLogRepository.cs +++ /dev/null @@ -1,29 +0,0 @@ -using TakeoutSaaS.Domain.Dictionary.Entities; - -namespace TakeoutSaaS.Domain.Dictionary.Repositories; - -/// -/// 缓存失效日志仓储。 -/// -public interface ICacheInvalidationLogRepository -{ - /// - /// 新增失效日志。 - /// - Task AddAsync(CacheInvalidationLog log, CancellationToken cancellationToken = default); - - /// - /// 分页查询失效日志。 - /// - Task<(IReadOnlyList Items, int TotalCount)> GetPagedAsync( - int page, - int pageSize, - DateTime? startDate, - DateTime? endDate, - CancellationToken cancellationToken = default); - - /// - /// 保存变更。 - /// - Task SaveChangesAsync(CancellationToken cancellationToken = default); -} diff --git a/src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/IDictionaryGroupRepository.cs b/src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/IDictionaryGroupRepository.cs deleted file mode 100644 index d7c5a76..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/IDictionaryGroupRepository.cs +++ /dev/null @@ -1,104 +0,0 @@ -using TakeoutSaaS.Domain.Dictionary.Entities; -using TakeoutSaaS.Domain.Dictionary.Enums; -using TakeoutSaaS.Domain.Dictionary.ValueObjects; - -namespace TakeoutSaaS.Domain.Dictionary.Repositories; - -/// -/// 字典分组仓储契约。 -/// -public interface IDictionaryGroupRepository -{ - /// - /// 按 ID 获取字典分组。 - /// - /// 分组 ID。 - /// 取消标记。 - /// 分组实体或 null。 - Task GetByIdAsync(long groupId, CancellationToken cancellationToken = default); - - /// - /// 按编码获取字典分组。 - /// - /// 租户 ID。 - /// 分组编码。 - /// 取消标记。 - /// 分组实体或 null。 - Task GetByCodeAsync(long tenantId, DictionaryCode code, CancellationToken cancellationToken = default); - - /// - /// 分页获取字典分组。 - /// - /// 租户 ID。 - /// 作用域过滤。 - /// 关键字过滤。 - /// 启用状态过滤。 - /// 页码。 - /// 页大小。 - /// 排序字段。 - /// 是否降序。 - /// 取消标记。 - /// 分组集合。 - Task> GetPagedAsync( - long tenantId, - DictionaryScope? scope, - string? keyword, - bool? isEnabled, - int page, - int pageSize, - string? sortBy, - bool sortDescending, - CancellationToken cancellationToken = default); - - /// - /// 获取满足条件的分组数量。 - /// - /// 租户 ID。 - /// 作用域过滤。 - /// 关键字过滤。 - /// 启用状态过滤。 - /// 取消标记。 - /// 分组数量。 - Task CountAsync( - long tenantId, - DictionaryScope? scope, - string? keyword, - bool? isEnabled, - CancellationToken cancellationToken = default); - - /// - /// 批量获取字典分组。 - /// - /// 分组 ID 列表。 - /// 取消标记。 - /// 分组集合。 - Task> GetByIdsAsync(IEnumerable groupIds, CancellationToken cancellationToken = default); - - /// - /// 新增分组。 - /// - /// 分组实体。 - /// 取消标记。 - Task AddAsync(DictionaryGroup group, CancellationToken cancellationToken = default); - - /// - /// 更新分组。 - /// - /// 分组实体。 - /// 取消标记。 - Task UpdateAsync(DictionaryGroup group, CancellationToken cancellationToken = default); - - /// - /// 删除分组。 - /// - /// 分组实体。 - /// 取消标记。 - Task RemoveAsync(DictionaryGroup group, CancellationToken cancellationToken = default); - - /// - /// 持久化更改。 - /// - /// 取消标记。 - /// 异步任务。 - Task SaveChangesAsync(CancellationToken cancellationToken = default); -} diff --git a/src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/IDictionaryImportLogRepository.cs b/src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/IDictionaryImportLogRepository.cs deleted file mode 100644 index cc659d1..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/IDictionaryImportLogRepository.cs +++ /dev/null @@ -1,22 +0,0 @@ -using TakeoutSaaS.Domain.Dictionary.Entities; - -namespace TakeoutSaaS.Domain.Dictionary.Repositories; - -/// -/// 字典导入日志仓储契约。 -/// -public interface IDictionaryImportLogRepository -{ - /// - /// 新增导入日志。 - /// - /// 导入日志。 - /// 取消标记。 - Task AddAsync(DictionaryImportLog log, CancellationToken cancellationToken = default); - - /// - /// 持久化更改。 - /// - /// 取消标记。 - Task SaveChangesAsync(CancellationToken cancellationToken = default); -} diff --git a/src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/IDictionaryItemRepository.cs b/src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/IDictionaryItemRepository.cs deleted file mode 100644 index 8ada246..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/IDictionaryItemRepository.cs +++ /dev/null @@ -1,64 +0,0 @@ -using TakeoutSaaS.Domain.Dictionary.Entities; - -namespace TakeoutSaaS.Domain.Dictionary.Repositories; - -/// -/// 字典项仓储契约。 -/// -public interface IDictionaryItemRepository -{ - /// - /// 根据 ID 获取字典项。 - /// - /// 字典项 ID。 - /// 取消标记。 - /// 字典项或 null。 - Task GetByIdAsync(long itemId, CancellationToken cancellationToken = default); - - /// - /// 获取分组下字典项列表。 - /// - /// 租户 ID。 - /// 分组 ID。 - /// 取消标记。 - /// 字典项集合。 - Task> GetByGroupIdAsync(long tenantId, long groupId, CancellationToken cancellationToken = default); - - /// - /// 获取合并后的系统/租户字典项。 - /// - /// 租户 ID。 - /// 系统分组 ID。 - /// 是否包含租户覆盖。 - /// 取消标记。 - /// 字典项集合。 - Task> GetMergedItemsAsync(long tenantId, long systemGroupId, bool includeOverrides, CancellationToken cancellationToken = default); - - /// - /// 新增字典项。 - /// - /// 字典项实体。 - /// 取消标记。 - Task AddAsync(DictionaryItem item, CancellationToken cancellationToken = default); - - /// - /// 更新字典项。 - /// - /// 字典项实体。 - /// 取消标记。 - Task UpdateAsync(DictionaryItem item, CancellationToken cancellationToken = default); - - /// - /// 删除字典项。 - /// - /// 字典项实体。 - /// 取消标记。 - Task RemoveAsync(DictionaryItem item, CancellationToken cancellationToken = default); - - /// - /// 持久化更改。 - /// - /// 取消标记。 - /// 异步任务。 - Task SaveChangesAsync(CancellationToken cancellationToken = default); -} diff --git a/src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/IDictionaryLabelOverrideRepository.cs b/src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/IDictionaryLabelOverrideRepository.cs deleted file mode 100644 index 12afd85..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/IDictionaryLabelOverrideRepository.cs +++ /dev/null @@ -1,65 +0,0 @@ -using TakeoutSaaS.Domain.Dictionary.Entities; -using TakeoutSaaS.Domain.Dictionary.Enums; - -namespace TakeoutSaaS.Domain.Dictionary.Repositories; - -/// -/// 字典标签覆盖仓储契约。 -/// -public interface IDictionaryLabelOverrideRepository -{ - /// - /// 根据 ID 获取覆盖配置。 - /// - Task GetByIdAsync(long id, CancellationToken cancellationToken = default); - - /// - /// 获取指定字典项的覆盖配置。 - /// - /// 租户 ID。 - /// 字典项 ID。 - /// 取消标记。 - Task GetByItemIdAsync(long tenantId, long dictionaryItemId, CancellationToken cancellationToken = default); - - /// - /// 获取租户的所有覆盖配置。 - /// - /// 租户 ID。 - /// 可选的覆盖类型过滤。 - /// 取消标记。 - Task> ListByTenantAsync( - long tenantId, - OverrideType? overrideType = null, - CancellationToken cancellationToken = default); - - /// - /// 批量获取多个字典项的覆盖配置。 - /// - /// 租户 ID。 - /// 字典项 ID 列表。 - /// 取消标记。 - Task> GetByItemIdsAsync( - long tenantId, - IEnumerable dictionaryItemIds, - CancellationToken cancellationToken = default); - - /// - /// 新增覆盖配置。 - /// - Task AddAsync(DictionaryLabelOverride entity, CancellationToken cancellationToken = default); - - /// - /// 更新覆盖配置。 - /// - Task UpdateAsync(DictionaryLabelOverride entity, CancellationToken cancellationToken = default); - - /// - /// 删除覆盖配置。 - /// - Task DeleteAsync(DictionaryLabelOverride entity, CancellationToken cancellationToken = default); - - /// - /// 持久化更改。 - /// - Task SaveChangesAsync(CancellationToken cancellationToken = default); -} diff --git a/src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/IDictionaryRepository.cs b/src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/IDictionaryRepository.cs deleted file mode 100644 index d0d4294..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/IDictionaryRepository.cs +++ /dev/null @@ -1,99 +0,0 @@ -using TakeoutSaaS.Domain.Dictionary.Entities; -using TakeoutSaaS.Domain.Dictionary.Enums; - -namespace TakeoutSaaS.Domain.Dictionary.Repositories; - -/// -/// 参数字典仓储契约。 -/// -public interface IDictionaryRepository -{ - /// - /// 依据 ID 获取分组。 - /// - /// 分组 ID。 - /// 取消标记。 - /// 分组实体或 null。 - Task FindGroupByIdAsync(long id, CancellationToken cancellationToken = default); - - /// - /// 依据编码获取分组。 - /// - /// 分组编码。 - /// 取消标记。 - /// 分组实体或 null。 - Task FindGroupByCodeAsync(string code, CancellationToken cancellationToken = default); - - /// - /// 搜索分组,可按作用域过滤。 - /// - /// 作用域。 - /// 取消标记。 - /// 分组集合。 - Task> SearchGroupsAsync(DictionaryScope? scope, CancellationToken cancellationToken = default); - - /// - /// 新增分组。 - /// - /// 分组实体。 - /// 取消标记。 - /// 异步任务。 - Task AddGroupAsync(DictionaryGroup group, CancellationToken cancellationToken = default); - - /// - /// 删除分组。 - /// - /// 分组实体。 - /// 取消标记。 - /// 异步任务。 - Task RemoveGroupAsync(DictionaryGroup group, CancellationToken cancellationToken = default); - - /// - /// 依据 ID 获取字典项。 - /// - /// 字典项 ID。 - /// 取消标记。 - /// 字典项或 null。 - Task FindItemByIdAsync(long id, CancellationToken cancellationToken = default); - - /// - /// 获取某分组下的所有字典项。 - /// - /// 分组 ID。 - /// 取消标记。 - /// 字典项集合。 - Task> GetItemsByGroupIdAsync(long groupId, CancellationToken cancellationToken = default); - - /// - /// 按分组编码集合获取字典项(可包含系统参数)。 - /// - /// 分组编码集合。 - /// 租户 ID。 - /// 是否包含系统分组。 - /// 取消标记。 - /// 字典项集合。 - Task> GetItemsByCodesAsync(IEnumerable codes, long tenantId, bool includeSystem, CancellationToken cancellationToken = default); - - /// - /// 新增字典项。 - /// - /// 字典项实体。 - /// 取消标记。 - /// 异步任务。 - Task AddItemAsync(DictionaryItem item, CancellationToken cancellationToken = default); - - /// - /// 删除字典项。 - /// - /// 字典项实体。 - /// 取消标记。 - /// 异步任务。 - Task RemoveItemAsync(DictionaryItem item, CancellationToken cancellationToken = default); - - /// - /// 持久化更改。 - /// - /// 取消标记。 - /// 异步任务。 - Task SaveChangesAsync(CancellationToken cancellationToken = default); -} diff --git a/src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/ITenantDictionaryOverrideRepository.cs b/src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/ITenantDictionaryOverrideRepository.cs deleted file mode 100644 index 72e5a1e..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/ITenantDictionaryOverrideRepository.cs +++ /dev/null @@ -1,47 +0,0 @@ -using TakeoutSaaS.Domain.Dictionary.Entities; - -namespace TakeoutSaaS.Domain.Dictionary.Repositories; - -/// -/// 租户字典覆盖仓储契约。 -/// -public interface ITenantDictionaryOverrideRepository -{ - /// - /// 获取租户覆盖配置。 - /// - /// 租户 ID。 - /// 系统字典分组 ID。 - /// 取消标记。 - /// 覆盖配置或 null。 - Task GetAsync(long tenantId, long systemGroupId, CancellationToken cancellationToken = default); - - /// - /// 获取租户全部覆盖配置。 - /// - /// 租户 ID。 - /// 取消标记。 - /// 覆盖配置列表。 - Task> ListAsync(long tenantId, CancellationToken cancellationToken = default); - - /// - /// 新增覆盖配置。 - /// - /// 覆盖配置。 - /// 取消标记。 - Task AddAsync(TenantDictionaryOverride overrideConfig, CancellationToken cancellationToken = default); - - /// - /// 更新覆盖配置。 - /// - /// 覆盖配置。 - /// 取消标记。 - Task UpdateAsync(TenantDictionaryOverride overrideConfig, CancellationToken cancellationToken = default); - - /// - /// 持久化更改。 - /// - /// 取消标记。 - /// 异步任务。 - Task SaveChangesAsync(CancellationToken cancellationToken = default); -} diff --git a/src/Domain/TakeoutSaaS.Domain/Dictionary/ValueObjects/I18nValue.cs b/src/Domain/TakeoutSaaS.Domain/Dictionary/ValueObjects/I18nValue.cs deleted file mode 100644 index 00ea1c2..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Dictionary/ValueObjects/I18nValue.cs +++ /dev/null @@ -1,151 +0,0 @@ -using System.Text.Encodings.Web; -using System.Text.Json; - -namespace TakeoutSaaS.Domain.Dictionary.ValueObjects; - -/// -/// 多语言字典值对象,封装语言键值映射。 -/// -public sealed class I18nValue : IEquatable -{ - private static readonly string[] FallbackLocales = ["zh-CN", "en"]; - private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web) - { - Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping - }; - private readonly Dictionary _values; - - /// - /// 初始化多语言值。 - /// - /// 语言键值映射。 - /// 传入值为空或无有效条目时抛出。 - public I18nValue(IDictionary values) - { - if (values == null) - { - throw new ArgumentNullException(nameof(values)); - } - - _values = new Dictionary(StringComparer.OrdinalIgnoreCase); - foreach (var (key, value) in values) - { - if (string.IsNullOrWhiteSpace(key) || string.IsNullOrWhiteSpace(value)) - { - continue; - } - - _values[key.Trim()] = value.Trim(); - } - - if (_values.Count == 0) - { - throw new ArgumentException("I18nValue requires at least one non-empty entry.", nameof(values)); - } - } - - /// - /// 语言键值只读视图。 - /// - public IReadOnlyDictionary Values => _values; - - /// - /// 获取指定语言值,支持回退策略。 - /// - /// 语言标识。 - /// 匹配语言值。 - public string Extract(string? locale) - { - if (!string.IsNullOrWhiteSpace(locale) && _values.TryGetValue(locale, out var value)) - { - return value; - } - - foreach (var fallback in FallbackLocales) - { - if (_values.TryGetValue(fallback, out var fallbackValue)) - { - return fallbackValue; - } - } - - return _values.Values.First(); - } - - /// - /// 转换为普通字典。 - /// - public Dictionary ToDictionary() - => new(_values, StringComparer.OrdinalIgnoreCase); - - /// - /// 转换为 JSON 字符串。 - /// - public string ToJson() - => JsonSerializer.Serialize(_values, JsonOptions); - - /// - /// 从 JSON 字符串解析多语言值。 - /// - public static I18nValue FromJson(string json) - { - if (string.IsNullOrWhiteSpace(json)) - { - throw new ArgumentException("JSON payload is required.", nameof(json)); - } - - var values = JsonSerializer.Deserialize>(json, JsonOptions) ?? new Dictionary(); - return new I18nValue(values); - } - - /// - public bool Equals(I18nValue? other) - { - if (other == null) - { - return false; - } - - if (ReferenceEquals(this, other)) - { - return true; - } - - if (_values.Count != other._values.Count) - { - return false; - } - - foreach (var (key, value) in _values) - { - if (!other._values.TryGetValue(key, out var otherValue)) - { - return false; - } - - if (!string.Equals(value, otherValue, StringComparison.Ordinal)) - { - return false; - } - } - - return true; - } - - /// - public override bool Equals(object? obj) - => obj is I18nValue other && Equals(other); - - /// - public override int GetHashCode() - { - var hash = new HashCode(); - foreach (var pair in _values.OrderBy(item => item.Key, StringComparer.OrdinalIgnoreCase)) - { - hash.Add(pair.Key, StringComparer.OrdinalIgnoreCase); - hash.Add(pair.Value, StringComparer.Ordinal); - } - - return hash.ToHashCode(); - } -} diff --git a/src/Domain/TakeoutSaaS.Domain/Identity/Repositories/IMiniUserRepository.cs b/src/Domain/TakeoutSaaS.Domain/Identity/Repositories/IMiniUserRepository.cs deleted file mode 100644 index 41594c2..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Identity/Repositories/IMiniUserRepository.cs +++ /dev/null @@ -1,37 +0,0 @@ -using TakeoutSaaS.Domain.Identity.Entities; - -namespace TakeoutSaaS.Domain.Identity.Repositories; - -/// -/// 小程序用户仓储契约。 -/// -public interface IMiniUserRepository -{ - /// - /// 根据微信 OpenId 查找小程序用户。 - /// - /// 微信 OpenId - /// 取消令牌 - /// 小程序用户,如果不存在则返回 null - Task FindByOpenIdAsync(string openId, CancellationToken cancellationToken = default); - - /// - /// 根据用户 ID 查找小程序用户。 - /// - /// 用户 ID - /// 取消令牌 - /// 小程序用户,如果不存在则返回 null - Task FindByIdAsync(long id, CancellationToken cancellationToken = default); - - /// - /// 创建或更新小程序用户(如果 OpenId 已存在则更新,否则创建)。 - /// - /// 微信 OpenId - /// 微信 UnionId(可选) - /// 昵称 - /// 头像地址(可选) - /// 租户 ID - /// 取消令牌 - /// 创建或更新后的小程序用户 - Task CreateOrUpdateAsync(string openId, string? unionId, string? nickname, string? avatar, long tenantId, CancellationToken cancellationToken = default); -} diff --git a/src/Domain/TakeoutSaaS.Domain/Identity/Repositories/IRoleTemplateRepository.cs b/src/Domain/TakeoutSaaS.Domain/Identity/Repositories/IRoleTemplateRepository.cs deleted file mode 100644 index f175722..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Identity/Repositories/IRoleTemplateRepository.cs +++ /dev/null @@ -1,74 +0,0 @@ -using TakeoutSaaS.Domain.Identity.Entities; - -namespace TakeoutSaaS.Domain.Identity.Repositories; - -/// -/// 角色模板仓储。 -/// -public interface IRoleTemplateRepository -{ - /// - /// 查询角色模板列表。 - /// - /// 启用状态过滤。 - /// 取消标记。 - /// 角色模板集合。 - Task> GetAllAsync(bool? isActive, CancellationToken cancellationToken = default); - - /// - /// 通过模板编码获取模板信息。 - /// - /// 模板编码。 - /// 取消标记。 - /// 模板实体或 null。 - Task FindByCodeAsync(string templateCode, CancellationToken cancellationToken = default); - - /// - /// 获取模板的权限列表。 - /// - /// 模板 ID。 - /// 取消标记。 - /// 权限集合。 - Task> GetPermissionsAsync(long roleTemplateId, CancellationToken cancellationToken = default); - - /// - /// 批量获取多个模板的权限映射。 - /// - /// 模板 ID 集合。 - /// 取消标记。 - /// 模板与权限列表的映射。 - Task>> GetPermissionsAsync(IEnumerable roleTemplateIds, CancellationToken cancellationToken = default); - - /// - /// 新增模板及其权限。 - /// - /// 模板实体。 - /// 权限编码集合。 - /// 取消标记。 - /// 异步操作任务。 - Task AddAsync(RoleTemplate template, IEnumerable permissionCodes, CancellationToken cancellationToken = default); - - /// - /// 更新模板及权限。 - /// - /// 模板实体。 - /// 权限编码集合。 - /// 取消标记。 - /// 异步操作任务。 - Task UpdateAsync(RoleTemplate template, IEnumerable permissionCodes, CancellationToken cancellationToken = default); - - /// - /// 删除模板。 - /// - /// 模板 ID。 - /// 取消标记。 - /// 异步操作任务。 - Task DeleteAsync(long roleTemplateId, CancellationToken cancellationToken = default); - - /// - /// 保存仓储变更。 - /// - /// 取消标记。 - /// 异步操作任务。 - Task SaveChangesAsync(CancellationToken cancellationToken = default); -} diff --git a/src/Domain/TakeoutSaaS.Domain/Inventory/Repositories/IInventoryRepository.cs b/src/Domain/TakeoutSaaS.Domain/Inventory/Repositories/IInventoryRepository.cs deleted file mode 100644 index bba4734..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Inventory/Repositories/IInventoryRepository.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System; -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using TakeoutSaaS.Domain.Inventory.Entities; -using TakeoutSaaS.Domain.Inventory.Enums; - -namespace TakeoutSaaS.Domain.Inventory.Repositories; - -/// -/// 库存仓储契约。 -/// -public interface IInventoryRepository -{ - /// - /// 依据标识查询库存。 - /// - Task FindByIdAsync(long inventoryItemId, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 按门店与 SKU 查询库存(只读)。 - /// - Task FindBySkuAsync(long tenantId, long storeId, long productSkuId, CancellationToken cancellationToken = default); - - /// - /// 按门店与 SKU 查询库存(跟踪用于更新)。 - /// - Task GetForUpdateAsync(long tenantId, long storeId, long productSkuId, CancellationToken cancellationToken = default); - - /// - /// 新增库存记录。 - /// - Task AddItemAsync(InventoryItem item, CancellationToken cancellationToken = default); - - /// - /// 更新库存记录。 - /// - Task UpdateItemAsync(InventoryItem item, CancellationToken cancellationToken = default); - - /// - /// 新增库存调整记录。 - /// - Task AddAdjustmentAsync(InventoryAdjustment adjustment, CancellationToken cancellationToken = default); - - /// - /// 新增锁定记录。 - /// - Task AddLockAsync(InventoryLockRecord lockRecord, CancellationToken cancellationToken = default); - - /// - /// 按幂等键查询锁记录。 - /// - Task FindLockByKeyAsync(long tenantId, string idempotencyKey, CancellationToken cancellationToken = default); - - /// - /// 更新锁状态。 - /// - Task MarkLockStatusAsync(InventoryLockRecord lockRecord, InventoryLockStatus status, CancellationToken cancellationToken = default); - - /// - /// 查询过期锁定。 - /// - Task> FindExpiredLocksAsync(long tenantId, DateTime utcNow, CancellationToken cancellationToken = default); - - /// - /// 查询批次列表。 - /// - Task> GetBatchesAsync(long tenantId, long storeId, long productSkuId, CancellationToken cancellationToken = default); - - /// - /// 批次扣减读取(带排序策略)。 - /// - Task> GetBatchesForConsumeAsync(long tenantId, long storeId, long productSkuId, InventoryBatchConsumeStrategy strategy, CancellationToken cancellationToken = default); - - /// - /// 查询批次(跟踪用于更新)。 - /// - Task GetBatchForUpdateAsync(long tenantId, long storeId, long productSkuId, string batchNumber, CancellationToken cancellationToken = default); - - /// - /// 新增批次。 - /// - Task AddBatchAsync(InventoryBatch batch, CancellationToken cancellationToken = default); - - /// - /// 更新批次。 - /// - Task UpdateBatchAsync(InventoryBatch batch, CancellationToken cancellationToken = default); - - /// - /// 持久化变更。 - /// - Task SaveChangesAsync(CancellationToken cancellationToken = default); -} diff --git a/src/Domain/TakeoutSaaS.Domain/Merchants/Repositories/IMerchantCategoryRepository.cs b/src/Domain/TakeoutSaaS.Domain/Merchants/Repositories/IMerchantCategoryRepository.cs deleted file mode 100644 index cabdd80..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Merchants/Repositories/IMerchantCategoryRepository.cs +++ /dev/null @@ -1,66 +0,0 @@ -using TakeoutSaaS.Domain.Merchants.Entities; - -namespace TakeoutSaaS.Domain.Merchants.Repositories; - -/// -/// 商户类目仓储契约。 -/// -public interface IMerchantCategoryRepository -{ - /// - /// 列出当前租户的类目。 - /// - /// 租户 ID。 - /// 取消标记。 - /// 类目列表。 - Task> ListAsync(long tenantId, CancellationToken cancellationToken = default); - - /// - /// 是否存在同名类目。 - /// - /// 类目名称。 - /// 租户 ID。 - /// 取消标记。 - /// 存在返回 true。 - Task ExistsAsync(string name, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 查找类目。 - /// - /// 类目 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 类目实体或 null。 - Task FindByIdAsync(long id, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 新增类目。 - /// - /// 类目实体。 - /// 取消标记。 - /// 异步任务。 - Task AddAsync(MerchantCategory category, CancellationToken cancellationToken = default); - - /// - /// 删除类目。 - /// - /// 类目实体。 - /// 取消标记。 - /// 异步任务。 - Task RemoveAsync(MerchantCategory category, CancellationToken cancellationToken = default); - - /// - /// 批量更新类目信息。 - /// - /// 类目集合。 - /// 取消标记。 - /// 异步任务。 - Task UpdateRangeAsync(IEnumerable categories, CancellationToken cancellationToken = default); - - /// - /// 持久化更改。 - /// - /// 取消标记。 - /// 异步任务。 - Task SaveChangesAsync(CancellationToken cancellationToken = default); -} diff --git a/src/Domain/TakeoutSaaS.Domain/Merchants/Services/IMerchantExportService.cs b/src/Domain/TakeoutSaaS.Domain/Merchants/Services/IMerchantExportService.cs deleted file mode 100644 index 19912e5..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Merchants/Services/IMerchantExportService.cs +++ /dev/null @@ -1,26 +0,0 @@ -using TakeoutSaaS.Domain.Merchants.Entities; -using TakeoutSaaS.Domain.Stores.Entities; - -namespace TakeoutSaaS.Domain.Merchants.Services; - -/// -/// 商户导出服务接口。 -/// -public interface IMerchantExportService -{ - /// - /// 导出为 PDF。 - /// - /// 商户主体。 - /// 租户名称。 - /// 门店列表。 - /// 审核历史。 - /// 取消标记。 - /// PDF 字节数组。 - Task ExportToPdfAsync( - Merchant merchant, - string? tenantName, - IReadOnlyList stores, - IReadOnlyList auditLogs, - CancellationToken cancellationToken = default); -} diff --git a/src/Domain/TakeoutSaaS.Domain/Orders/Repositories/IOrderRepository.cs b/src/Domain/TakeoutSaaS.Domain/Orders/Repositories/IOrderRepository.cs deleted file mode 100644 index 96a3bd6..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Orders/Repositories/IOrderRepository.cs +++ /dev/null @@ -1,122 +0,0 @@ -using TakeoutSaaS.Domain.Orders.Entities; -using TakeoutSaaS.Domain.Orders.Enums; -using TakeoutSaaS.Domain.Payments.Enums; - -namespace TakeoutSaaS.Domain.Orders.Repositories; - -/// -/// 订单聚合仓储契约。 -/// -public interface IOrderRepository -{ - /// - /// 依据标识获取订单。 - /// - /// 订单 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 订单实体或 null。 - Task FindByIdAsync(long orderId, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 依据订单号获取订单。 - /// - /// 订单号。 - /// 租户 ID。 - /// 取消标记。 - /// 订单实体或 null。 - Task FindByOrderNoAsync(string orderNo, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 按状态筛选订单列表。 - /// - /// 租户 ID。 - /// 订单状态。 - /// 支付状态。 - /// 取消标记。 - /// 订单集合。 - Task> SearchAsync(long tenantId, OrderStatus? status, PaymentStatus? paymentStatus, CancellationToken cancellationToken = default); - - /// - /// 获取订单明细行。 - /// - /// 订单 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 订单明细集合。 - Task> GetItemsAsync(long orderId, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 获取订单状态流转记录。 - /// - /// 订单 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 状态变更记录列表。 - Task> GetStatusHistoryAsync(long orderId, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 获取订单退款申请。 - /// - /// 订单 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 退款申请列表。 - Task> GetRefundsAsync(long orderId, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 新增订单。 - /// - /// 订单实体。 - /// 取消标记。 - /// 异步任务。 - Task AddOrderAsync(Order order, CancellationToken cancellationToken = default); - - /// - /// 新增订单明细。 - /// - /// 明细集合。 - /// 取消标记。 - /// 异步任务。 - Task AddItemsAsync(IEnumerable items, CancellationToken cancellationToken = default); - - /// - /// 新增订单状态记录。 - /// - /// 状态记录。 - /// 取消标记。 - /// 异步任务。 - Task AddStatusHistoryAsync(OrderStatusHistory history, CancellationToken cancellationToken = default); - - /// - /// 新增退款申请。 - /// - /// 退款申请实体。 - /// 取消标记。 - /// 异步任务。 - Task AddRefundAsync(RefundRequest refund, CancellationToken cancellationToken = default); - - /// - /// 持久化变更。 - /// - /// 取消标记。 - /// 异步任务。 - Task SaveChangesAsync(CancellationToken cancellationToken = default); - - /// - /// 更新订单。 - /// - /// 订单实体。 - /// 取消标记。 - /// 异步任务。 - Task UpdateOrderAsync(Order order, CancellationToken cancellationToken = default); - - /// - /// 删除订单。 - /// - /// 订单 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 异步任务。 - Task DeleteOrderAsync(long orderId, long tenantId, CancellationToken cancellationToken = default); -} diff --git a/src/Domain/TakeoutSaaS.Domain/Payments/Repositories/IPaymentRepository.cs b/src/Domain/TakeoutSaaS.Domain/Payments/Repositories/IPaymentRepository.cs deleted file mode 100644 index 7983a5a..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Payments/Repositories/IPaymentRepository.cs +++ /dev/null @@ -1,86 +0,0 @@ -using TakeoutSaaS.Domain.Payments.Entities; -using TakeoutSaaS.Domain.Payments.Enums; - -namespace TakeoutSaaS.Domain.Payments.Repositories; - -/// -/// 支付记录仓储契约。 -/// -public interface IPaymentRepository -{ - /// - /// 依据标识获取支付记录。 - /// - /// 支付记录 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 支付记录或 null。 - Task FindByIdAsync(long paymentId, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 依据订单标识获取支付记录。 - /// - /// 订单 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 支付记录或 null。 - Task FindByOrderIdAsync(long orderId, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 获取支付对应的退款记录。 - /// - /// 支付记录 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 退款记录列表。 - Task> GetRefundsAsync(long paymentId, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 新增支付记录。 - /// - /// 支付实体。 - /// 取消标记。 - /// 异步任务。 - Task AddPaymentAsync(PaymentRecord payment, CancellationToken cancellationToken = default); - - /// - /// 新增退款记录。 - /// - /// 退款实体。 - /// 取消标记。 - /// 异步任务。 - Task AddRefundAsync(PaymentRefundRecord refund, CancellationToken cancellationToken = default); - - /// - /// 持久化变更。 - /// - /// 取消标记。 - /// 异步任务。 - Task SaveChangesAsync(CancellationToken cancellationToken = default); - - /// - /// 按状态筛选支付记录。 - /// - /// 租户 ID。 - /// 支付状态。 - /// 取消标记。 - /// 支付记录列表。 - Task> SearchAsync(long tenantId, PaymentStatus? status, CancellationToken cancellationToken = default); - - /// - /// 更新支付记录。 - /// - /// 支付实体。 - /// 取消标记。 - /// 异步任务。 - Task UpdatePaymentAsync(PaymentRecord payment, CancellationToken cancellationToken = default); - - /// - /// 删除支付记录及关联退款。 - /// - /// 支付记录 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 异步任务。 - Task DeletePaymentAsync(long paymentId, long tenantId, CancellationToken cancellationToken = default); -} diff --git a/src/Domain/TakeoutSaaS.Domain/Products/Repositories/IProductRepository.cs b/src/Domain/TakeoutSaaS.Domain/Products/Repositories/IProductRepository.cs deleted file mode 100644 index 5b4563a..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Products/Repositories/IProductRepository.cs +++ /dev/null @@ -1,268 +0,0 @@ -using TakeoutSaaS.Domain.Products.Entities; -using TakeoutSaaS.Domain.Products.Enums; - -namespace TakeoutSaaS.Domain.Products.Repositories; - -/// -/// 商品聚合仓储契约。 -/// -public interface IProductRepository -{ - /// - /// 依据标识获取商品。 - /// - Task FindByIdAsync(long productId, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 按分类与状态筛选商品列表。 - /// - Task> SearchAsync(long tenantId, long? storeId, long? categoryId, ProductStatus? status, CancellationToken cancellationToken = default, DateTime? updatedAfter = null); - - /// - /// 获取租户下的商品分类。 - /// - Task> GetCategoriesAsync(long tenantId, CancellationToken cancellationToken = default); - - /// - /// 获取门店商品分类。 - /// - Task> GetCategoriesByStoreAsync(long tenantId, long storeId, bool onlyEnabled = true, CancellationToken cancellationToken = default); - - /// - /// 获取商品 SKU。 - /// - Task> GetSkusAsync(long productId, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 批量获取商品 SKU。 - /// - Task> GetSkusByProductIdsAsync(IReadOnlyCollection productIds, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 获取商品加料组与选项。 - /// - /// 商品 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 加料组集合。 - Task> GetAddonGroupsAsync(long productId, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 批量获取商品加料组。 - /// - Task> GetAddonGroupsByProductIdsAsync(IReadOnlyCollection productIds, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 获取商品加料选项。 - /// - /// 商品 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 加料选项集合。 - Task> GetAddonOptionsAsync(long productId, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 批量获取商品加料选项。 - /// - Task> GetAddonOptionsByGroupIdsAsync(IReadOnlyCollection addonGroupIds, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 获取商品规格组与选项。 - /// - /// 商品 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 规格组集合。 - Task> GetAttributeGroupsAsync(long productId, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 批量获取商品规格组。 - /// - Task> GetAttributeGroupsByProductIdsAsync(IReadOnlyCollection productIds, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 获取商品规格选项。 - /// - /// 商品 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 规格选项集合。 - Task> GetAttributeOptionsAsync(long productId, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 批量获取商品规格选项。 - /// - Task> GetAttributeOptionsByGroupIdsAsync(IReadOnlyCollection attributeGroupIds, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 获取商品媒资。 - /// - /// 商品 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 媒资列表。 - Task> GetMediaAssetsAsync(long productId, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 批量获取商品媒资。 - /// - Task> GetMediaAssetsByProductIdsAsync(IReadOnlyCollection productIds, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 获取商品定价规则。 - /// - /// 商品 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 定价规则集合。 - Task> GetPricingRulesAsync(long productId, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 批量获取商品定价规则。 - /// - Task> GetPricingRulesByProductIdsAsync(IReadOnlyCollection productIds, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 新增分类。 - /// - /// 分类实体。 - /// 取消标记。 - /// 异步任务。 - Task AddCategoryAsync(ProductCategory category, CancellationToken cancellationToken = default); - - /// - /// 新增商品。 - /// - /// 商品实体。 - /// 取消标记。 - /// 异步任务。 - Task AddProductAsync(Product product, CancellationToken cancellationToken = default); - - /// - /// 新增 SKU。 - /// - /// SKU 集合。 - /// 取消标记。 - /// 异步任务。 - Task AddSkusAsync(IEnumerable skus, CancellationToken cancellationToken = default); - - /// - /// 新增加料组与选项。 - /// - /// 加料组集合。 - /// 加料选项集合。 - /// 取消标记。 - /// 异步任务。 - Task AddAddonGroupsAsync(IEnumerable groups, IEnumerable options, CancellationToken cancellationToken = default); - - /// - /// 新增规格组与选项。 - /// - /// 规格组集合。 - /// 规格选项集合。 - /// 取消标记。 - /// 异步任务。 - Task AddAttributeGroupsAsync(IEnumerable groups, IEnumerable options, CancellationToken cancellationToken = default); - - /// - /// 新增媒资。 - /// - /// 媒资集合。 - /// 取消标记。 - /// 异步任务。 - Task AddMediaAssetsAsync(IEnumerable assets, CancellationToken cancellationToken = default); - - /// - /// 新增定价规则。 - /// - /// 定价规则集合。 - /// 取消标记。 - /// 异步任务。 - Task AddPricingRulesAsync(IEnumerable rules, CancellationToken cancellationToken = default); - - /// - /// 持久化变更。 - /// - /// 取消标记。 - /// 异步任务。 - Task SaveChangesAsync(CancellationToken cancellationToken = default); - - /// - /// 更新商品。 - /// - /// 商品实体。 - /// 取消标记。 - /// 异步任务。 - Task UpdateProductAsync(Product product, CancellationToken cancellationToken = default); - - /// - /// 删除商品。 - /// - /// 商品 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 异步任务。 - Task DeleteProductAsync(long productId, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 更新分类。 - /// - /// 分类实体。 - /// 取消标记。 - /// 异步任务。 - Task UpdateCategoryAsync(ProductCategory category, CancellationToken cancellationToken = default); - - /// - /// 删除分类。 - /// - /// 分类 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 异步任务。 - Task DeleteCategoryAsync(long categoryId, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 删除商品下的 SKU。 - /// - /// 商品 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 异步任务。 - Task RemoveSkusAsync(long productId, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 删除商品下的加料组及选项。 - /// - /// 商品 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 异步任务。 - Task RemoveAddonGroupsAsync(long productId, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 删除商品下的规格组及选项。 - /// - /// 商品 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 异步任务。 - Task RemoveAttributeGroupsAsync(long productId, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 删除商品媒资。 - /// - /// 商品 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 异步任务。 - Task RemoveMediaAssetsAsync(long productId, long tenantId, CancellationToken cancellationToken = default); - - /// - /// 删除商品定价规则。 - /// - /// 商品 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 异步任务。 - Task RemovePricingRulesAsync(long productId, long tenantId, CancellationToken cancellationToken = default); -} diff --git a/src/Domain/TakeoutSaaS.Domain/Stores/Events/StoreApprovedEvent.cs b/src/Domain/TakeoutSaaS.Domain/Stores/Events/StoreApprovedEvent.cs deleted file mode 100644 index da3199a..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Stores/Events/StoreApprovedEvent.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace TakeoutSaaS.Domain.Stores.Events; - -/// -/// 门店审核通过事件。 -/// -public sealed class StoreApprovedEvent -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 租户 ID。 - /// - public long TenantId { get; init; } - - /// - /// 审核通过时间(UTC)。 - /// - public DateTime ApprovedAt { get; init; } -} diff --git a/src/Domain/TakeoutSaaS.Domain/Stores/Events/StoreForceClosedEvent.cs b/src/Domain/TakeoutSaaS.Domain/Stores/Events/StoreForceClosedEvent.cs deleted file mode 100644 index f2f6016..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Stores/Events/StoreForceClosedEvent.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace TakeoutSaaS.Domain.Stores.Events; - -/// -/// 门店强制关闭事件。 -/// -public sealed class StoreForceClosedEvent -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 租户 ID。 - /// - public long TenantId { get; init; } - - /// - /// 强制关闭原因。 - /// - public string? Reason { get; init; } - - /// - /// 强制关闭时间(UTC)。 - /// - public DateTime ForceClosedAt { get; init; } -} diff --git a/src/Domain/TakeoutSaaS.Domain/Stores/Events/StoreRejectedEvent.cs b/src/Domain/TakeoutSaaS.Domain/Stores/Events/StoreRejectedEvent.cs deleted file mode 100644 index a0ab258..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Stores/Events/StoreRejectedEvent.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace TakeoutSaaS.Domain.Stores.Events; - -/// -/// 门店审核驳回事件。 -/// -public sealed class StoreRejectedEvent -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 租户 ID。 - /// - public long TenantId { get; init; } - - /// - /// 驳回理由 ID。 - /// - public long? RejectionReasonId { get; init; } - - /// - /// 驳回理由文本。 - /// - public string? RejectionReason { get; init; } - - /// - /// 驳回时间(UTC)。 - /// - public DateTime RejectedAt { get; init; } -} diff --git a/src/Domain/TakeoutSaaS.Domain/Stores/Events/StoreSubmittedEvent.cs b/src/Domain/TakeoutSaaS.Domain/Stores/Events/StoreSubmittedEvent.cs deleted file mode 100644 index 9279ebf..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Stores/Events/StoreSubmittedEvent.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace TakeoutSaaS.Domain.Stores.Events; - -/// -/// 门店提交审核事件。 -/// -public sealed class StoreSubmittedEvent -{ - /// - /// 门店 ID。 - /// - public long StoreId { get; init; } - - /// - /// 租户 ID。 - /// - public long TenantId { get; init; } - - /// - /// 提交时间(UTC)。 - /// - public DateTime SubmittedAt { get; init; } -} diff --git a/src/Domain/TakeoutSaaS.Domain/SystemParameters/Repositories/ISystemParameterRepository.cs b/src/Domain/TakeoutSaaS.Domain/SystemParameters/Repositories/ISystemParameterRepository.cs deleted file mode 100644 index ced9e53..0000000 --- a/src/Domain/TakeoutSaaS.Domain/SystemParameters/Repositories/ISystemParameterRepository.cs +++ /dev/null @@ -1,65 +0,0 @@ -using TakeoutSaaS.Domain.SystemParameters.Entities; - -namespace TakeoutSaaS.Domain.SystemParameters.Repositories; - -/// -/// 系统参数仓储接口:提供基础 CRUD 与查询能力。 -/// -public interface ISystemParameterRepository -{ - /// - /// 根据标识获取系统参数。 - /// - /// 参数 ID。 - /// 取消标记。 - /// 系统参数或 null。 - Task FindByIdAsync(long id, CancellationToken cancellationToken = default); - - /// - /// 根据键获取系统参数(当前租户)。 - /// - /// 参数键。 - /// 取消标记。 - /// 系统参数或 null。 - Task FindByKeyAsync(string key, CancellationToken cancellationToken = default); - - /// - /// 查询系统参数列表。 - /// - /// 关键字。 - /// 启用状态。 - /// 取消标记。 - /// 参数列表。 - Task> SearchAsync(string? keyword, bool? isEnabled, CancellationToken cancellationToken = default); - - /// - /// 新增系统参数。 - /// - /// 参数实体。 - /// 取消标记。 - /// 异步任务。 - Task AddAsync(SystemParameter parameter, CancellationToken cancellationToken = default); - - /// - /// 删除系统参数。 - /// - /// 参数实体。 - /// 取消标记。 - /// 异步任务。 - Task RemoveAsync(SystemParameter parameter, CancellationToken cancellationToken = default); - - /// - /// 更新系统参数。 - /// - /// 参数实体。 - /// 取消标记。 - /// 异步任务。 - Task UpdateAsync(SystemParameter parameter, CancellationToken cancellationToken = default); - - /// - /// 持久化更改。 - /// - /// 取消标记。 - /// 异步任务。 - Task SaveChangesAsync(CancellationToken cancellationToken = default); -} diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Enums/BillingExportFormat.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Enums/BillingExportFormat.cs deleted file mode 100644 index 19765f2..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Tenants/Enums/BillingExportFormat.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace TakeoutSaaS.Domain.Tenants.Enums; - -/// -/// 账单导出格式。 -/// -public enum BillingExportFormat -{ - /// - /// Excel 格式(.xlsx)。 - /// - Excel = 0, - - /// - /// PDF 格式(.pdf)。 - /// - Pdf = 1, - - /// - /// CSV 格式(.csv)。 - /// - Csv = 2 -} diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Events/AnnouncementPublished.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Events/AnnouncementPublished.cs deleted file mode 100644 index 59fe5b4..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Tenants/Events/AnnouncementPublished.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace TakeoutSaaS.Domain.Tenants.Events; - -/// -/// 公告发布事件。 -/// -public sealed class AnnouncementPublished -{ - /// - /// 公告 ID。 - /// - public long AnnouncementId { get; init; } - - /// - /// 发布时间(UTC)。 - /// - public DateTime PublishedAt { get; init; } - - /// - /// 目标受众类型。 - /// - public string TargetType { get; init; } = string.Empty; -} diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Events/AnnouncementRevoked.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Events/AnnouncementRevoked.cs deleted file mode 100644 index a49fe09..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Tenants/Events/AnnouncementRevoked.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace TakeoutSaaS.Domain.Tenants.Events; - -/// -/// 公告撤销事件。 -/// -public sealed class AnnouncementRevoked -{ - /// - /// 公告 ID。 - /// - public long AnnouncementId { get; init; } - - /// - /// 撤销时间(UTC)。 - /// - public DateTime RevokedAt { get; init; } -} diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/IQuotaPackageRepository.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/IQuotaPackageRepository.cs deleted file mode 100644 index 49aa91d..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/IQuotaPackageRepository.cs +++ /dev/null @@ -1,131 +0,0 @@ -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; - -namespace TakeoutSaaS.Domain.Tenants.Repositories; - -/// -/// 配额包仓储。 -/// -public interface IQuotaPackageRepository -{ - #region 配额包定义 - - /// - /// 按 ID 查找配额包。 - /// - /// 配额包 ID(雪花算法)。 - /// 取消标记。 - /// 配额包实体,未找到返回 null。 - Task FindByIdAsync(long id, CancellationToken cancellationToken = default); - - /// - /// 分页查询配额包。 - /// - /// 配额类型,为空不按类型过滤。 - /// 启用状态,为空不按状态过滤。 - /// 页码(从 1 开始)。 - /// 每页大小。 - /// 取消标记。 - /// 分页数据与总数。 - Task<(IReadOnlyList Items, int Total)> SearchPagedAsync( - TenantQuotaType? quotaType, - bool? isActive, - int page, - int pageSize, - CancellationToken cancellationToken = default); - - /// - /// 新增配额包。 - /// - /// 配额包实体。 - /// 取消标记。 - /// 异步任务。 - Task AddAsync(QuotaPackage quotaPackage, CancellationToken cancellationToken = default); - - /// - /// 更新配额包。 - /// - /// 配额包实体。 - /// 取消标记。 - /// 异步任务。 - Task UpdateAsync(QuotaPackage quotaPackage, CancellationToken cancellationToken = default); - - /// - /// 软删除配额包。 - /// - /// 配额包 ID(雪花算法)。 - /// 取消标记。 - /// 删除成功返回 true,未找到返回 false。 - Task SoftDeleteAsync(long id, CancellationToken cancellationToken = default); - - #endregion - - #region 配额包购买记录 - - /// - /// 分页查询租户配额购买记录(包含配额包信息)。 - /// - /// 租户 ID(雪花算法)。 - /// 页码(从 1 开始)。 - /// 每页大小。 - /// 取消标记。 - /// 分页数据与总数。 - Task<(IReadOnlyList<(TenantQuotaPackagePurchase Purchase, QuotaPackage Package)> Items, int Total)> GetPurchasesPagedAsync( - long tenantId, - int page, - int pageSize, - CancellationToken cancellationToken = default); - - /// - /// 新增配额购买记录。 - /// - /// 购买记录实体。 - /// 取消标记。 - /// 异步任务。 - Task AddPurchaseAsync(TenantQuotaPackagePurchase purchase, CancellationToken cancellationToken = default); - - #endregion - - #region 配额使用情况 - - /// - /// 查询租户配额使用情况。 - /// - /// 租户 ID(雪花算法)。 - /// 配额类型,为空查询全部。 - /// 取消标记。 - /// 配额使用情况列表。 - Task> GetUsageByTenantAsync( - long tenantId, - TenantQuotaType? quotaType, - CancellationToken cancellationToken = default); - - /// - /// 查找特定配额使用记录。 - /// - /// 租户 ID(雪花算法)。 - /// 配额类型。 - /// 取消标记。 - /// 配额使用记录,未找到返回 null。 - Task FindUsageAsync( - long tenantId, - TenantQuotaType quotaType, - CancellationToken cancellationToken = default); - - /// - /// 更新配额使用情况。 - /// - /// 配额使用实体。 - /// 取消标记。 - /// 异步任务。 - Task UpdateUsageAsync(TenantQuotaUsage usage, CancellationToken cancellationToken = default); - - #endregion - - /// - /// 持久化。 - /// - /// 取消标记。 - /// 异步任务。 - Task SaveChangesAsync(CancellationToken cancellationToken = default); -} diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/IStatisticsRepository.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/IStatisticsRepository.cs deleted file mode 100644 index 806d440..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/IStatisticsRepository.cs +++ /dev/null @@ -1,112 +0,0 @@ -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; - -namespace TakeoutSaaS.Domain.Tenants.Repositories; - -/// -/// 统计数据仓储接口。 -/// -public interface IStatisticsRepository -{ - #region 订阅统计 - - /// - /// 获取所有订阅(用于统计)。 - /// - /// 取消标记。 - /// 所有订阅记录。 - Task> GetAllSubscriptionsAsync(CancellationToken cancellationToken = default); - - /// - /// 获取即将到期的订阅(含租户和套餐信息)。 - /// - /// 到期天数。 - /// 是否仅查询未开启自动续费的。 - /// 取消标记。 - /// 即将到期的订阅信息列表。 - Task> GetExpiringSubscriptionsAsync( - int daysAhead, - bool onlyWithoutAutoRenew, - CancellationToken cancellationToken = default); - - #endregion - - #region 收入统计 - - /// - /// 获取所有已付款账单(用于收入统计)。 - /// - /// 取消标记。 - /// 已付款账单列表。 - Task> GetPaidBillsAsync(CancellationToken cancellationToken = default); - - #endregion - - #region 配额使用排行 - - /// - /// 获取配额使用排行(含租户信息)。 - /// - /// 配额类型。 - /// 前 N 名。 - /// 取消标记。 - /// 配额使用排行列表。 - Task> GetQuotaUsageRankingAsync( - TenantQuotaType quotaType, - int topN, - CancellationToken cancellationToken = default); - - #endregion -} - -/// -/// 即将到期的订阅信息(含关联数据)。 -/// -public record ExpiringSubscriptionInfo -{ - /// - /// 订阅实体。 - /// - public required TenantSubscription Subscription { get; init; } - - /// - /// 租户名称。 - /// - public required string TenantName { get; init; } - - /// - /// 套餐名称。 - /// - public required string PackageName { get; init; } -} - -/// -/// 配额使用排行信息(含租户名称)。 -/// -public record QuotaUsageRankInfo -{ - /// - /// 租户 ID。 - /// - public long TenantId { get; init; } - - /// - /// 租户名称。 - /// - public required string TenantName { get; init; } - - /// - /// 已使用值。 - /// - public decimal UsedValue { get; init; } - - /// - /// 限制值。 - /// - public decimal LimitValue { get; init; } - - /// - /// 使用百分比。 - /// - public decimal UsagePercentage { get; init; } -} diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ISubscriptionRepository.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ISubscriptionRepository.cs deleted file mode 100644 index f72d8d3..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ISubscriptionRepository.cs +++ /dev/null @@ -1,382 +0,0 @@ -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; - -namespace TakeoutSaaS.Domain.Tenants.Repositories; - -/// -/// 订阅管理仓储接口。 -/// -public interface ISubscriptionRepository -{ - #region 订阅查询 - - /// - /// 按 ID 查询订阅。 - /// - /// 订阅 ID。 - /// 取消标记。 - /// 订阅实体,未找到返回 null。 - Task FindByIdAsync( - long subscriptionId, - CancellationToken cancellationToken = default); - - /// - /// 按 ID 列表批量查询订阅。 - /// - /// 订阅 ID 列表。 - /// 取消标记。 - /// 订阅实体列表。 - Task> FindByIdsAsync( - IEnumerable subscriptionIds, - CancellationToken cancellationToken = default); - - /// - /// 分页查询订阅列表(含关联信息)。 - /// - /// 查询过滤条件。 - /// 取消标记。 - /// 分页结果。 - Task<(IReadOnlyList Items, int Total)> SearchPagedAsync( - SubscriptionSearchFilter filter, - CancellationToken cancellationToken = default); - - /// - /// 获取订阅详情(含关联信息)。 - /// - /// 订阅 ID。 - /// 取消标记。 - /// 订阅详情信息。 - Task GetDetailAsync( - long subscriptionId, - CancellationToken cancellationToken = default); - - /// - /// 按 ID 列表批量查询订阅(含租户信息)。 - /// - /// 订阅 ID 列表。 - /// 取消标记。 - /// 订阅与租户信息列表。 - Task> FindByIdsWithTenantAsync( - IEnumerable subscriptionIds, - CancellationToken cancellationToken = default); - - /// - /// 查询自动续费候选订阅(活跃 + 开启自动续费 + 即将到期)。 - /// - /// 当前时间(UTC)。 - /// 续费阈值时间(UTC),到期时间小于等于该时间视为候选。 - /// 取消标记。 - /// 候选订阅集合(含套餐信息)。 - Task> FindAutoRenewalCandidatesAsync( - DateTime now, - DateTime renewalThreshold, - CancellationToken cancellationToken = default); - - /// - /// 查询续费提醒候选订阅(活跃 + 未开启自动续费 + 到期时间落在指定日期范围)。 - /// - /// 筛选开始时间(UTC,含)。 - /// 筛选结束时间(UTC,不含)。 - /// 取消标记。 - /// 候选订阅集合(含租户与套餐信息)。 - Task> FindRenewalReminderCandidatesAsync( - DateTime startOfDay, - DateTime endOfDay, - CancellationToken cancellationToken = default); - - /// - /// 查询已到期仍处于 Active 的订阅(用于进入宽限期)。 - /// - /// 当前时间(UTC)。 - /// 取消标记。 - /// 到期订阅集合。 - Task> FindExpiredActiveSubscriptionsAsync( - DateTime now, - CancellationToken cancellationToken = default); - - /// - /// 查询宽限期已结束的订阅(用于自动暂停)。 - /// - /// 当前时间(UTC)。 - /// 宽限期天数。 - /// 取消标记。 - /// 宽限期到期订阅集合。 - Task> FindGracePeriodExpiredSubscriptionsAsync( - DateTime now, - int gracePeriodDays, - CancellationToken cancellationToken = default); - - #endregion - - #region 套餐查询 - - /// - /// 按 ID 查询套餐。 - /// - /// 套餐 ID。 - /// 取消标记。 - /// 套餐实体,未找到返回 null。 - Task FindPackageByIdAsync(long packageId, CancellationToken cancellationToken = default); - - #endregion - - #region 订阅更新 - - /// - /// 更新订阅。 - /// - /// 订阅实体。 - /// 取消标记。 - Task UpdateAsync(TenantSubscription subscription, CancellationToken cancellationToken = default); - - #endregion - - #region 订阅历史 - - /// - /// 添加订阅变更历史。 - /// - /// 历史记录实体。 - /// 取消标记。 - Task AddHistoryAsync(TenantSubscriptionHistory history, CancellationToken cancellationToken = default); - - /// - /// 获取订阅变更历史(含套餐名称)。 - /// - /// 订阅 ID。 - /// 取消标记。 - /// 历史记录列表。 - Task> GetHistoryAsync( - long subscriptionId, - CancellationToken cancellationToken = default); - - #endregion - - #region 配额使用 - - /// - /// 获取租户配额使用情况。 - /// - /// 租户 ID。 - /// 取消标记。 - /// 配额使用列表。 - Task> GetQuotaUsagesAsync( - long tenantId, - CancellationToken cancellationToken = default); - - #endregion - - #region 通知 - - /// - /// 添加租户通知。 - /// - /// 通知实体。 - /// 取消标记。 - Task AddNotificationAsync(TenantNotification notification, CancellationToken cancellationToken = default); - - #endregion - - #region 操作日志 - - /// - /// 添加操作日志。 - /// - /// 日志实体。 - /// 取消标记。 - Task AddOperationLogAsync(OperationLog log, CancellationToken cancellationToken = default); - - #endregion - - /// - /// 保存变更。 - /// - /// 取消标记。 - Task SaveChangesAsync(CancellationToken cancellationToken = default); -} - -#region 查询过滤与结果类型 - -/// -/// 订阅查询过滤条件。 -/// -public record SubscriptionSearchFilter -{ - /// - /// 订阅状态。 - /// - public SubscriptionStatus? Status { get; init; } - - /// - /// 套餐 ID。 - /// - public long? TenantPackageId { get; init; } - - /// - /// 租户 ID。 - /// - public long? TenantId { get; init; } - - /// - /// 租户关键词(名称或编码)。 - /// - public string? TenantKeyword { get; init; } - - /// - /// 即将到期天数。 - /// - public int? ExpiringWithinDays { get; init; } - - /// - /// 自动续费状态。 - /// - public bool? AutoRenew { get; init; } - - /// - /// 页码(从 1 开始)。 - /// - public int Page { get; init; } = 1; - - /// - /// 每页数量。 - /// - public int PageSize { get; init; } = 20; -} - -/// -/// 订阅及关联信息。 -/// -public record SubscriptionWithRelations -{ - /// - /// 订阅实体。 - /// - public required TenantSubscription Subscription { get; init; } - - /// - /// 租户名称。 - /// - public required string TenantName { get; init; } - - /// - /// 租户编码。 - /// - public required string TenantCode { get; init; } - - /// - /// 套餐名称。 - /// - public required string PackageName { get; init; } - - /// - /// 排期套餐名称(可选)。 - /// - public string? ScheduledPackageName { get; init; } -} - -/// -/// 订阅详情信息。 -/// -public record SubscriptionDetailInfo -{ - /// - /// 订阅实体。 - /// - public required TenantSubscription Subscription { get; init; } - - /// - /// 租户名称。 - /// - public required string TenantName { get; init; } - - /// - /// 租户编码。 - /// - public required string TenantCode { get; init; } - - /// - /// 当前套餐。 - /// - public TenantPackage? Package { get; init; } - - /// - /// 排期套餐。 - /// - public TenantPackage? ScheduledPackage { get; init; } -} - -/// -/// 订阅与租户信息。 -/// -public record SubscriptionWithTenant -{ - /// - /// 订阅实体。 - /// - public required TenantSubscription Subscription { get; init; } - - /// - /// 租户实体。 - /// - public required Tenant Tenant { get; init; } -} - -/// -/// 自动续费候选订阅信息。 -/// -public sealed record AutoRenewalCandidate -{ - /// - /// 订阅实体。 - /// - public required TenantSubscription Subscription { get; init; } - - /// - /// 当前套餐实体。 - /// - public required TenantPackage Package { get; init; } -} - -/// -/// 续费提醒候选订阅信息。 -/// -public sealed record RenewalReminderCandidate -{ - /// - /// 订阅实体。 - /// - public required TenantSubscription Subscription { get; init; } - - /// - /// 租户实体。 - /// - public required Tenant Tenant { get; init; } - - /// - /// 当前套餐实体。 - /// - public required TenantPackage Package { get; init; } -} - -/// -/// 订阅历史(含套餐名称)。 -/// -public record SubscriptionHistoryWithPackageNames -{ - /// - /// 历史记录实体。 - /// - public required TenantSubscriptionHistory History { get; init; } - - /// - /// 原套餐名称。 - /// - public required string FromPackageName { get; init; } - - /// - /// 目标套餐名称。 - /// - public required string ToPackageName { get; init; } -} - -#endregion diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ITenantAnnouncementReadRepository.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ITenantAnnouncementReadRepository.cs deleted file mode 100644 index 53af993..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ITenantAnnouncementReadRepository.cs +++ /dev/null @@ -1,53 +0,0 @@ -using TakeoutSaaS.Domain.Tenants.Entities; - -namespace TakeoutSaaS.Domain.Tenants.Repositories; - -/// -/// 公告已读仓储。 -/// -public interface ITenantAnnouncementReadRepository -{ - /// - /// 按公告查询已读记录。 - /// - /// 租户 ID。 - /// 公告 ID。 - /// 取消标记。 - /// 指定公告的已读列表。 - Task> GetByAnnouncementAsync(long tenantId, long announcementId, CancellationToken cancellationToken = default); - - /// - /// 批量按公告查询已读记录,可选按用户过滤。 - /// - /// 租户 ID。 - /// 公告 ID 集合。 - /// 用户 ID,空则不按用户筛选。 - /// 取消标记。 - /// 匹配条件的已读列表。 - Task> GetByAnnouncementAsync(long tenantId, IEnumerable announcementIds, long? userId, CancellationToken cancellationToken = default); - - /// - /// 查询指定用户对某公告的已读记录。 - /// - /// 租户 ID。 - /// 公告 ID。 - /// 用户 ID。 - /// 取消标记。 - /// 已读记录,未读返回 null。 - Task FindAsync(long tenantId, long announcementId, long? userId, CancellationToken cancellationToken = default); - - /// - /// 新增已读记录。 - /// - /// 已读实体。 - /// 取消标记。 - /// 异步任务。 - Task AddAsync(TenantAnnouncementRead record, CancellationToken cancellationToken = default); - - /// - /// 保存变更。 - /// - /// 取消标记。 - /// 异步任务。 - Task SaveChangesAsync(CancellationToken cancellationToken = default); -} diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ITenantAnnouncementRepository.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ITenantAnnouncementRepository.cs deleted file mode 100644 index dd2deee..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ITenantAnnouncementRepository.cs +++ /dev/null @@ -1,97 +0,0 @@ -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; - -namespace TakeoutSaaS.Domain.Tenants.Repositories; - -/// -/// 租户公告仓储。 -/// -public interface ITenantAnnouncementRepository -{ - /// - /// 查询公告列表,按类型、状态与生效时间筛选。 - /// - /// 租户 ID。 - /// 关键词(标题/内容)。 - /// 公告状态。 - /// 公告类型。 - /// 启用状态。 - /// 生效开始时间筛选。 - /// 生效结束时间筛选。 - /// 生效时间点,为空不限制。 - /// 是否按优先级降序和生效时间降序排序,默认 false。 - /// 限制返回数量,为空不限制。 - /// 取消标记。 - /// 公告集合。 - Task> SearchAsync( - long tenantId, - string? keyword, - AnnouncementStatus? status, - TenantAnnouncementType? type, - bool? isActive, - DateTime? effectiveFrom, - DateTime? effectiveTo, - DateTime? effectiveAt, - bool orderByPriority = false, - int? limit = null, - CancellationToken cancellationToken = default); - - /// - /// 查询未读公告。 - /// - /// 租户 ID。 - /// 用户 ID。 - /// 公告状态。 - /// 启用状态。 - /// 生效时间点,为空不限制。 - /// 取消标记。 - /// 未读公告集合。 - Task> SearchUnreadAsync( - long tenantId, - long? userId, - AnnouncementStatus? status, - bool? isActive, - DateTime? effectiveAt, - CancellationToken cancellationToken = default); - - /// - /// 按 ID 获取公告。 - /// - /// 租户 ID。 - /// 公告 ID。 - /// 取消标记。 - /// 公告实体或 null。 - Task FindByIdAsync(long tenantId, long announcementId, CancellationToken cancellationToken = default); - - /// - /// 新增公告。 - /// - /// 公告实体。 - /// 取消标记。 - /// 异步任务。 - Task AddAsync(TenantAnnouncement announcement, CancellationToken cancellationToken = default); - - /// - /// 更新公告。 - /// - /// 公告实体。 - /// 取消标记。 - /// 异步任务。 - Task UpdateAsync(TenantAnnouncement announcement, CancellationToken cancellationToken = default); - - /// - /// 删除公告。 - /// - /// 租户 ID。 - /// 公告 ID。 - /// 取消标记。 - /// 异步任务。 - Task DeleteAsync(long tenantId, long announcementId, CancellationToken cancellationToken = default); - - /// - /// 保存变更。 - /// - /// 取消标记。 - /// 异步任务。 - Task SaveChangesAsync(CancellationToken cancellationToken = default); -} diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ITenantQuotaUsageHistoryRepository.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ITenantQuotaUsageHistoryRepository.cs deleted file mode 100644 index 927f5d4..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ITenantQuotaUsageHistoryRepository.cs +++ /dev/null @@ -1,23 +0,0 @@ -using TakeoutSaaS.Domain.Tenants.Entities; - -namespace TakeoutSaaS.Domain.Tenants.Repositories; - -/// -/// 租户配额使用历史仓储。 -/// -public interface ITenantQuotaUsageHistoryRepository -{ - /// - /// 新增历史记录。 - /// - /// 历史记录实体。 - /// 取消标记。 - Task AddAsync(TenantQuotaUsageHistory history, CancellationToken cancellationToken = default); - - /// - /// 持久化。 - /// - /// 取消标记。 - Task SaveChangesAsync(CancellationToken cancellationToken = default); -} - diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Services/IBillingDomainService.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Services/IBillingDomainService.cs deleted file mode 100644 index a1a0680..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Tenants/Services/IBillingDomainService.cs +++ /dev/null @@ -1,64 +0,0 @@ -using TakeoutSaaS.Domain.Tenants.Entities; - -namespace TakeoutSaaS.Domain.Tenants.Services; - -/// -/// 账单领域服务接口。 -/// 负责处理账单生成、账单编号生成、逾期处理等跨实体的业务逻辑。 -/// -public interface IBillingDomainService -{ - /// - /// 根据订阅信息生成账单。 - /// - /// 租户订阅信息。 - /// 取消标记。 - /// 生成的账单实体。 - Task GenerateSubscriptionBillingAsync( - TenantSubscription subscription, - CancellationToken cancellationToken = default); - - /// - /// 根据配额包购买信息生成账单。 - /// - /// 租户 ID。 - /// 配额包信息。 - /// 购买数量。 - /// 取消标记。 - /// 生成的账单实体。 - Task GenerateQuotaPurchaseBillingAsync( - long tenantId, - QuotaPackage quotaPackage, - int quantity, - CancellationToken cancellationToken = default); - - /// - /// 生成唯一的账单编号。 - /// 格式示例:BIL-20251217-000001 - /// - /// 账单编号。 - string GenerateStatementNo(); - - /// - /// 处理逾期账单(批量标记逾期状态)。 - /// - /// 取消标记。 - /// 处理的账单数量。 - Task ProcessOverdueBillingsAsync(CancellationToken cancellationToken = default); - - /// - /// 计算账单总金额(含折扣和税费)。 - /// - /// 基础金额。 - /// 折扣金额。 - /// 税费金额。 - /// 总金额。 - decimal CalculateTotalAmount(decimal baseAmount, decimal discountAmount, decimal taxAmount); - - /// - /// 验证账单状态是否可以进行支付操作。 - /// - /// 账单实体。 - /// 是否可以支付。 - bool CanProcessPayment(TenantBillingStatement billing); -} diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Services/IBillingExportService.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Services/IBillingExportService.cs deleted file mode 100644 index a9882b1..0000000 --- a/src/Domain/TakeoutSaaS.Domain/Tenants/Services/IBillingExportService.cs +++ /dev/null @@ -1,33 +0,0 @@ -using TakeoutSaaS.Domain.Tenants.Entities; - -namespace TakeoutSaaS.Domain.Tenants.Services; - -/// -/// 账单导出服务接口。 -/// -public interface IBillingExportService -{ - /// - /// 导出为 Excel(XLSX)。 - /// - /// 账单数据。 - /// 取消标记。 - /// 文件字节数组。 - Task ExportToExcelAsync(IReadOnlyList billings, CancellationToken cancellationToken = default); - - /// - /// 导出为 PDF。 - /// - /// 账单数据。 - /// 取消标记。 - /// 文件字节数组。 - Task ExportToPdfAsync(IReadOnlyList billings, CancellationToken cancellationToken = default); - - /// - /// 导出为 CSV。 - /// - /// 账单数据。 - /// 取消标记。 - /// 文件字节数组。 - Task ExportToCsvAsync(IReadOnlyList billings, CancellationToken cancellationToken = default); -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Extensions/AppServiceCollectionExtensions.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Extensions/AppServiceCollectionExtensions.cs deleted file mode 100644 index 2fb0b1f..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Extensions/AppServiceCollectionExtensions.cs +++ /dev/null @@ -1,86 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using TakeoutSaaS.Application.App.Stores.Services; -using TakeoutSaaS.Domain.Deliveries.Repositories; -using TakeoutSaaS.Domain.Inventory.Repositories; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Domain.Merchants.Services; -using TakeoutSaaS.Domain.Orders.Repositories; -using TakeoutSaaS.Domain.Payments.Repositories; -using TakeoutSaaS.Domain.Products.Repositories; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Domain.Tenants.Services; -using TakeoutSaaS.Infrastructure.App.Options; -using TakeoutSaaS.Infrastructure.App.Persistence; -using TakeoutSaaS.Infrastructure.Logs.Persistence; -using TakeoutSaaS.Infrastructure.Logs.Repositories; -using TakeoutSaaS.Infrastructure.App.Persistence.Repositories; -using TakeoutSaaS.Infrastructure.App.Repositories; -using TakeoutSaaS.Infrastructure.App.Services; -using TakeoutSaaS.Infrastructure.Common.Extensions; -using TakeoutSaaS.Shared.Abstractions.Constants; - -namespace TakeoutSaaS.Infrastructure.App.Extensions; - -/// -/// 业务主库基础设施注册扩展。 -/// -public static class AppServiceCollectionExtensions -{ - /// - /// 注册业务主库 DbContext 与仓储。 - /// - /// 服务集合。 - /// 配置源。 - /// 服务集合。 - public static IServiceCollection AddAppInfrastructure(this IServiceCollection services, IConfiguration configuration) - { - services.AddDatabaseInfrastructure(configuration); - services.AddPostgresDbContext(DatabaseConstants.AppDataSource); - services.AddPostgresDbContext(DatabaseConstants.LogsDataSource); - - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - - // 1. 账单领域/导出服务 - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - - // 2. (空行后) 门店配置服务 - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - - // 3. (空行后) 初始化配置与种子 - services.AddOptions() - .Bind(configuration.GetSection(AppSeedOptions.SectionName)) - .ValidateDataAnnotations(); - - services.AddHostedService(); - - return services; - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Options/AppSeedOptions.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Options/AppSeedOptions.cs deleted file mode 100644 index 4099e12..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Options/AppSeedOptions.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace TakeoutSaaS.Infrastructure.App.Options; - -/// -/// 业务数据种子配置。 -/// -public sealed class AppSeedOptions -{ - /// - /// 配置节名称。 - /// - public const string SectionName = "App:Seed"; - - /// - /// 是否启用业务数据种子。 - /// - public bool Enabled { get; set; } - - /// - /// 默认租户配置。 - /// - public TenantSeedOptions? DefaultTenant { get; set; } - - /// - /// 基础字典分组。 - /// - public List DictionaryGroups { get; set; } = new(); - - /// - /// 系统参数配置。 - /// - public List SystemParameters { get; set; } = new(); -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Options/DictionarySeedGroupOptions.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Options/DictionarySeedGroupOptions.cs deleted file mode 100644 index c59ebb4..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Options/DictionarySeedGroupOptions.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using TakeoutSaaS.Domain.Dictionary.Enums; - -namespace TakeoutSaaS.Infrastructure.App.Options; - -/// -/// 字典分组种子配置。 -/// -public sealed class DictionarySeedGroupOptions -{ - /// - /// 所属租户,不填则使用默认租户或系统租户。 - /// - public long? TenantId { get; set; } - - /// - /// 分组编码。 - /// - [Required] - [MaxLength(64)] - public string Code { get; set; } = string.Empty; - - /// - /// 分组名称。 - /// - [Required] - [MaxLength(128)] - public string Name { get; set; } = string.Empty; - - /// - /// 分组作用域。 - /// - public DictionaryScope Scope { get; set; } = DictionaryScope.Business; - - /// - /// 描述信息。 - /// - [MaxLength(512)] - public string? Description { get; set; } - - /// - /// 是否启用。 - /// - public bool IsEnabled { get; set; } = true; - - /// - /// 字典项集合。 - /// - public List Items { get; set; } = new(); -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Options/DictionarySeedItemOptions.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Options/DictionarySeedItemOptions.cs deleted file mode 100644 index 6d3ea0b..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Options/DictionarySeedItemOptions.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Infrastructure.App.Options; - -/// -/// 字典项种子配置。 -/// -public sealed class DictionarySeedItemOptions -{ - /// - /// 字典项键。 - /// - [Required] - [MaxLength(64)] - public string Key { get; set; } = string.Empty; - - /// - /// 字典项值。 - /// - [Required] - [MaxLength(256)] - public string Value { get; set; } = string.Empty; - - /// - /// 描述。 - /// - [MaxLength(512)] - public string? Description { get; set; } - - /// - /// 排序。 - /// - public int SortOrder { get; set; } = 100; - - /// - /// 是否启用。 - /// - public bool IsEnabled { get; set; } = true; -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Options/SystemParameterSeedOptions.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Options/SystemParameterSeedOptions.cs deleted file mode 100644 index a9df90b..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Options/SystemParameterSeedOptions.cs +++ /dev/null @@ -1,37 +0,0 @@ -namespace TakeoutSaaS.Infrastructure.App.Options; - -/// -/// 系统参数种子配置项。 -/// -public sealed class SystemParameterSeedOptions -{ - /// - /// 目标租户,null 时使用默认租户或 0。 - /// - public long? TenantId { get; set; } - - /// - /// 参数键。 - /// - public string Key { get; set; } = string.Empty; - - /// - /// 参数值。 - /// - public string Value { get; set; } = string.Empty; - - /// - /// 说明。 - /// - public string? Description { get; set; } - - /// - /// 排序。 - /// - public int SortOrder { get; set; } - - /// - /// 是否启用。 - /// - public bool IsEnabled { get; set; } = true; -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Options/TenantSeedOptions.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Options/TenantSeedOptions.cs deleted file mode 100644 index 044e4e6..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Options/TenantSeedOptions.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Infrastructure.App.Options; - -/// -/// 默认租户种子配置。 -/// -public sealed class TenantSeedOptions -{ - /// - /// 自定义租户标识,不填则自动生成。 - /// - public long TenantId { get; set; } - - /// - /// 租户编码。 - /// - [Required] - [MaxLength(64)] - public string Code { get; set; } = string.Empty; - - /// - /// 租户名称。 - /// - [Required] - [MaxLength(128)] - public string Name { get; set; } = string.Empty; - - /// - /// 租户简称。 - /// - [MaxLength(128)] - public string? ShortName { get; set; } - - /// - /// 联系人姓名。 - /// - [MaxLength(64)] - public string? ContactName { get; set; } - - /// - /// 联系电话。 - /// - [MaxLength(32)] - public string? ContactPhone { get; set; } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/AppDataSeeder.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/AppDataSeeder.cs deleted file mode 100644 index 079a573..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/AppDataSeeder.cs +++ /dev/null @@ -1,494 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using TakeoutSaaS.Domain.Dictionary.Entities; -using TakeoutSaaS.Domain.SystemParameters.Entities; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Infrastructure.App.Options; -using TakeoutSaaS.Infrastructure.Dictionary.Persistence; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Infrastructure.App.Persistence; - -/// -/// 业务数据种子,确保默认租户与基础字典可重复执行。 -/// -/// -/// 初始化种子服务。 -/// -public sealed class AppDataSeeder( - IServiceProvider serviceProvider, - ILogger logger, - IOptions options) : IHostedService -{ - private readonly AppSeedOptions _options = options.Value; - - - /// - public async Task StartAsync(CancellationToken cancellationToken) - { - if (!_options.Enabled) - { - logger.LogInformation("AppSeed 未启用,跳过业务数据初始化"); - return; - } - - using var scope = serviceProvider.CreateScope(); - var appDbContext = scope.ServiceProvider.GetRequiredService(); - var dictionaryDbContext = scope.ServiceProvider.GetRequiredService(); - var tenantContextAccessor = scope.ServiceProvider.GetRequiredService(); - - await EnsureSystemTenantAsync(appDbContext, cancellationToken); - var defaultTenantId = await EnsureDefaultTenantAsync(appDbContext, cancellationToken); - await EnsureDictionarySeedsAsync(dictionaryDbContext, tenantContextAccessor, defaultTenantId, cancellationToken); - - logger.LogInformation("AppSeed 完成业务数据初始化"); - } - - /// - public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; - - /// - /// 确保默认租户存在。 - /// - private async Task EnsureDefaultTenantAsync(TakeoutAppDbContext dbContext, CancellationToken cancellationToken) - { - using var _ = dbContext.DisableSoftDeleteFilter(); - var tenantOptions = _options.DefaultTenant; - if (tenantOptions == null || string.IsNullOrWhiteSpace(tenantOptions.Code) || string.IsNullOrWhiteSpace(tenantOptions.Name)) - { - logger.LogInformation("AppSeed 未配置默认租户,跳过租户种子"); - return null; - } - - var code = tenantOptions.Code.Trim(); - var existingTenant = await dbContext.Tenants - .FirstOrDefaultAsync(x => x.Code == code, cancellationToken); - - if (existingTenant == null) - { - var tenant = new Tenant - { - Id = tenantOptions.TenantId, - Code = code, - Name = tenantOptions.Name.Trim(), - ShortName = tenantOptions.ShortName?.Trim(), - ContactName = tenantOptions.ContactName?.Trim(), - ContactPhone = tenantOptions.ContactPhone?.Trim(), - Status = TenantStatus.Active - }; - - await dbContext.Tenants.AddAsync(tenant, cancellationToken); - await dbContext.SaveChangesAsync(cancellationToken); - logger.LogInformation("AppSeed 已创建默认租户 {TenantCode}", code); - return tenant.Id; - } - - var updated = false; - - if (existingTenant.DeletedAt.HasValue) - { - existingTenant.DeletedAt = null; - existingTenant.DeletedBy = null; - updated = true; - } - - if (!string.Equals(existingTenant.Name, tenantOptions.Name, StringComparison.Ordinal)) - { - existingTenant.Name = tenantOptions.Name.Trim(); - updated = true; - } - - if (!string.Equals(existingTenant.ShortName, tenantOptions.ShortName, StringComparison.Ordinal)) - { - existingTenant.ShortName = tenantOptions.ShortName?.Trim(); - updated = true; - } - - if (!string.Equals(existingTenant.ContactName, tenantOptions.ContactName, StringComparison.Ordinal)) - { - existingTenant.ContactName = tenantOptions.ContactName?.Trim(); - updated = true; - } - - if (!string.Equals(existingTenant.ContactPhone, tenantOptions.ContactPhone, StringComparison.Ordinal)) - { - existingTenant.ContactPhone = tenantOptions.ContactPhone?.Trim(); - updated = true; - } - - if (existingTenant.Status != TenantStatus.Active) - { - existingTenant.Status = TenantStatus.Active; - updated = true; - } - - if (updated) - { - dbContext.Tenants.Update(existingTenant); - await dbContext.SaveChangesAsync(cancellationToken); - logger.LogInformation("AppSeed 已更新默认租户 {TenantCode}", code); - } - else - { - logger.LogInformation("AppSeed 默认租户 {TenantCode} 已存在且无需更新", code); - } - - return existingTenant.Id; - } - - /// - /// 确保系统租户存在(TenantId=0,用于系统级数据归属)。 - /// - private async Task EnsureSystemTenantAsync(TakeoutAppDbContext dbContext, CancellationToken cancellationToken) - { - using var _ = dbContext.DisableSoftDeleteFilter(); - var existingTenant = await dbContext.Tenants - .FirstOrDefaultAsync(x => x.Id == 0, cancellationToken); - - if (existingTenant != null) - { - // 1. (空行后) 若历史数据仍为 PLATFORM,则自动修正为 SYSTEM - var updated = false; - - if (existingTenant.DeletedAt.HasValue) - { - existingTenant.DeletedAt = null; - existingTenant.DeletedBy = null; - updated = true; - } - if (!string.Equals(existingTenant.Code, "SYSTEM", StringComparison.Ordinal)) - { - existingTenant.Code = "SYSTEM"; - updated = true; - } - - if (!string.Equals(existingTenant.Name, "System", StringComparison.Ordinal)) - { - existingTenant.Name = "System"; - updated = true; - } - - if (existingTenant.Status != TenantStatus.Active) - { - existingTenant.Status = TenantStatus.Active; - updated = true; - } - - if (updated) - { - dbContext.Tenants.Update(existingTenant); - await dbContext.SaveChangesAsync(cancellationToken); - logger.LogInformation("AppSeed 已更新系统租户 SYSTEM"); - } - - return; - } - - var tenant = new Tenant - { - Id = 0, - Code = "SYSTEM", - Name = "System", - Status = TenantStatus.Active - }; - - await dbContext.Tenants.AddAsync(tenant, cancellationToken); - await dbContext.SaveChangesAsync(cancellationToken); - logger.LogInformation("AppSeed 已创建系统租户 SYSTEM"); - } - - /// - /// 确保基础字典存在。 - /// - private async Task EnsureDictionarySeedsAsync( - DictionaryDbContext dbContext, - ITenantContextAccessor tenantContextAccessor, - long? defaultTenantId, - CancellationToken cancellationToken) - { - var dictionaryGroups = _options.DictionaryGroups ?? new List(); - var hasDictionaryGroups = dictionaryGroups.Count > 0; - - if (!hasDictionaryGroups) - { - logger.LogInformation("AppSeed 未配置基础字典,跳过字典种子"); - } - - if (hasDictionaryGroups) - { - foreach (var groupOptions in dictionaryGroups) - { - if (string.IsNullOrWhiteSpace(groupOptions.Code) || string.IsNullOrWhiteSpace(groupOptions.Name)) - { - logger.LogWarning("AppSeed 跳过字典分组,Code 或 Name 为空"); - continue; - } - - var tenantId = groupOptions.TenantId ?? defaultTenantId ?? 0; - var code = groupOptions.Code.Trim(); - - using var tenantScope = tenantContextAccessor.EnterTenantScope(tenantId, "app-seed"); - using var disableSoftDeleteScope = dbContext.DisableSoftDeleteFilter(); - var group = await dbContext.DictionaryGroups - .FirstOrDefaultAsync(x => x.Code == code, cancellationToken); - - if (group == null) - { - group = new DictionaryGroup - { - Id = 0, - TenantId = tenantId, - Code = code, - Name = groupOptions.Name.Trim(), - Scope = groupOptions.Scope, - Description = groupOptions.Description?.Trim(), - IsEnabled = groupOptions.IsEnabled - }; - - await dbContext.DictionaryGroups.AddAsync(group, cancellationToken); - logger.LogInformation("AppSeed 创建字典分组 {GroupCode} (Tenant: {TenantId})", code, tenantId); - } - else - { - var groupUpdated = false; - - if (group.DeletedAt.HasValue) - { - group.DeletedAt = null; - group.DeletedBy = null; - groupUpdated = true; - } - - if (!string.Equals(group.Name, groupOptions.Name, StringComparison.Ordinal)) - { - group.Name = groupOptions.Name.Trim(); - groupUpdated = true; - } - - if (!string.Equals(group.Description, groupOptions.Description, StringComparison.Ordinal)) - { - group.Description = groupOptions.Description?.Trim(); - groupUpdated = true; - } - - if (group.Scope != groupOptions.Scope) - { - group.Scope = groupOptions.Scope; - groupUpdated = true; - } - - if (group.IsEnabled != groupOptions.IsEnabled) - { - group.IsEnabled = groupOptions.IsEnabled; - groupUpdated = true; - } - - if (groupUpdated) - { - dbContext.DictionaryGroups.Update(group); - } - } - - await UpsertDictionaryItemsAsync(dbContext, group, groupOptions.Items, tenantId, cancellationToken); - } - } - - await EnsureSystemParametersAsync(dbContext, tenantContextAccessor, defaultTenantId, cancellationToken); - await dbContext.SaveChangesAsync(cancellationToken); - } - - - /// - /// 确保系统参数以独立表形式可重复种子。 - /// - private async Task EnsureSystemParametersAsync( - DictionaryDbContext dbContext, - ITenantContextAccessor tenantContextAccessor, - long? defaultTenantId, - CancellationToken cancellationToken) - { - var systemParameters = _options.SystemParameters ?? new List(); - - if (systemParameters.Count == 0) - { - logger.LogInformation("AppSeed 未配置系统参数,跳过系统参数种子"); - return; - } - - var grouped = systemParameters - .Where(x => !string.IsNullOrWhiteSpace(x.Key) && !string.IsNullOrWhiteSpace(x.Value)) - .GroupBy(x => x.TenantId ?? defaultTenantId ?? 0); - - if (!grouped.Any()) - { - logger.LogInformation("AppSeed 系统参数配置为空,跳过系统参数种子"); - return; - } - - foreach (var group in grouped) - { - var tenantId = group.Key; - using var tenantScope = tenantContextAccessor.EnterTenantScope(tenantId, "app-seed"); - using var disableSoftDeleteScope = dbContext.DisableSoftDeleteFilter(); - var existingParameters = await dbContext.SystemParameters - .ToListAsync(cancellationToken); - - foreach (var seed in group) - { - var key = seed.Key.Trim(); - var existing = existingParameters.FirstOrDefault(x => x.Key.Equals(key, StringComparison.OrdinalIgnoreCase)); - - if (existing == null) - { - var parameter = new SystemParameter - { - Id = 0, - TenantId = tenantId, - Key = key, - Value = seed.Value.Trim(), - Description = seed.Description?.Trim(), - SortOrder = seed.SortOrder, - IsEnabled = seed.IsEnabled - }; - - await dbContext.SystemParameters.AddAsync(parameter, cancellationToken); - continue; - } - - var updated = false; - - if (existing.DeletedAt.HasValue) - { - existing.DeletedAt = null; - existing.DeletedBy = null; - updated = true; - } - - if (!string.Equals(existing.Value, seed.Value, StringComparison.Ordinal)) - { - existing.Value = seed.Value.Trim(); - updated = true; - } - - if (!string.Equals(existing.Description, seed.Description, StringComparison.Ordinal)) - { - existing.Description = seed.Description?.Trim(); - updated = true; - } - - if (existing.SortOrder != seed.SortOrder) - { - existing.SortOrder = seed.SortOrder; - updated = true; - } - - if (existing.IsEnabled != seed.IsEnabled) - { - existing.IsEnabled = seed.IsEnabled; - updated = true; - } - - if (updated) - { - dbContext.SystemParameters.Update(existing); - } - } - } - } - - /// - /// 合并字典项。 - /// - private static async Task UpsertDictionaryItemsAsync( - DictionaryDbContext dbContext, - DictionaryGroup group, - IEnumerable seedItems, - long tenantId, - CancellationToken cancellationToken) - { - // 确保分组已持久化以获取正确的主键,避免 FK 约束报错。 - if (!dbContext.Entry(group).IsKeySet || group.Id == 0) - { - await dbContext.SaveChangesAsync(cancellationToken); - } - - var materializedItems = seedItems - .Where(item => !string.IsNullOrWhiteSpace(item.Key) && !string.IsNullOrWhiteSpace(item.Value)) - .ToList(); - - if (materializedItems.Count == 0) - { - return; - } - - var existingItems = await dbContext.DictionaryItems - .Where(x => x.GroupId == group.Id) - .ToListAsync(cancellationToken); - - foreach (var seed in materializedItems) - { - var key = seed.Key.Trim(); - var existing = existingItems.FirstOrDefault(x => x.Key.Equals(key, StringComparison.OrdinalIgnoreCase)); - - if (existing == null) - { - var newItem = new DictionaryItem - { - Id = 0, - TenantId = tenantId, - GroupId = group.Id, - Key = key, - Value = seed.Value.Trim(), - Description = seed.Description?.Trim(), - SortOrder = seed.SortOrder, - IsEnabled = seed.IsEnabled - }; - - await dbContext.DictionaryItems.AddAsync(newItem, cancellationToken); - continue; - } - - var updated = false; - - if (existing.DeletedAt.HasValue) - { - existing.DeletedAt = null; - existing.DeletedBy = null; - updated = true; - } - - if (!string.Equals(existing.Value, seed.Value, StringComparison.Ordinal)) - { - existing.Value = seed.Value.Trim(); - updated = true; - } - - if (!string.Equals(existing.Description, seed.Description, StringComparison.Ordinal)) - { - existing.Description = seed.Description?.Trim(); - updated = true; - } - - if (existing.SortOrder != seed.SortOrder) - { - existing.SortOrder = seed.SortOrder; - updated = true; - } - - if (existing.IsEnabled != seed.IsEnabled) - { - existing.IsEnabled = seed.IsEnabled; - updated = true; - } - - if (updated) - { - dbContext.DictionaryItems.Update(existing); - } - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/Configurations/TenantBillingStatementConfiguration.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/Configurations/TenantBillingStatementConfiguration.cs deleted file mode 100644 index d40970f..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/Configurations/TenantBillingStatementConfiguration.cs +++ /dev/null @@ -1,51 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; - -namespace TakeoutSaaS.Infrastructure.App.Persistence.Configurations; - -/// -/// EF Core 映射配置。 -/// -public sealed class TenantBillingStatementConfiguration : IEntityTypeConfiguration -{ - /// - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("tenant_billing_statements"); - builder.HasKey(x => x.Id); - - // 1. 字段约束 - builder.Property(x => x.StatementNo).HasMaxLength(64).IsRequired(); - builder.Property(x => x.BillingType).HasConversion(); - builder.Property(x => x.AmountDue).HasPrecision(18, 2); - builder.Property(x => x.DiscountAmount).HasPrecision(18, 2); - builder.Property(x => x.TaxAmount).HasPrecision(18, 2); - builder.Property(x => x.AmountPaid).HasPrecision(18, 2); - builder.Property(x => x.Currency).HasMaxLength(8).HasDefaultValue("CNY"); - builder.Property(x => x.Status).HasConversion(); - - // 2. JSON 字段(当前以 text 存储 JSON 字符串,便于兼容历史迁移) - builder.Property(x => x.LineItemsJson).HasColumnType("text"); - - // 3. 备注字段 - builder.Property(x => x.Notes).HasMaxLength(512); - - // 4. 唯一约束与索引 - builder.HasIndex(x => new { x.TenantId, x.StatementNo }).IsUnique(); - - // 5. 性能索引(高频查询:租户+状态+到期日) - builder.HasIndex(x => new { x.TenantId, x.Status, x.DueDate }) - .HasDatabaseName("idx_billing_tenant_status_duedate"); - - // 6. 逾期扫描索引(仅索引 Pending/Overdue) - builder.HasIndex(x => new { x.Status, x.DueDate }) - .HasDatabaseName("idx_billing_status_duedate") - .HasFilter($"\"Status\" IN ({(int)TenantBillingStatus.Pending}, {(int)TenantBillingStatus.Overdue})"); - - // 7. 创建时间索引(支持列表倒序) - builder.HasIndex(x => x.CreatedAt) - .HasDatabaseName("idx_billing_created_at"); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/Configurations/TenantPaymentConfiguration.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/Configurations/TenantPaymentConfiguration.cs deleted file mode 100644 index 114a31c..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/Configurations/TenantPaymentConfiguration.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; -using TakeoutSaaS.Domain.Tenants.Entities; - -namespace TakeoutSaaS.Infrastructure.App.Persistence.Configurations; - -/// -/// EF Core 映射配置。 -/// -public sealed class TenantPaymentConfiguration : IEntityTypeConfiguration -{ - /// - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("tenant_payments"); - builder.HasKey(x => x.Id); - - // 1. 字段约束 - builder.Property(x => x.BillingStatementId).IsRequired(); - builder.Property(x => x.Amount).HasPrecision(18, 2).IsRequired(); - builder.Property(x => x.Method).HasConversion(); - builder.Property(x => x.Status).HasConversion(); - builder.Property(x => x.TransactionNo).HasMaxLength(64); - builder.Property(x => x.ProofUrl).HasMaxLength(512); - builder.Property(x => x.RefundReason).HasMaxLength(512); - builder.Property(x => x.Notes).HasMaxLength(512); - - // 2. 复合索引:租户+账单 - builder.HasIndex(x => new { x.TenantId, x.BillingStatementId }); - - // 3. 支付记录时间排序索引 - builder.HasIndex(x => new { x.BillingStatementId, x.PaidAt }) - .HasDatabaseName("idx_payment_billing_paidat"); - - // 4. 交易号索引(部分索引:仅非空) - builder.HasIndex(x => x.TransactionNo) - .HasDatabaseName("idx_payment_transaction_no") - .HasFilter("\"TransactionNo\" IS NOT NULL"); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/Repositories/TenantBillingRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/Repositories/TenantBillingRepository.cs deleted file mode 100644 index 07b6eb5..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/Repositories/TenantBillingRepository.cs +++ /dev/null @@ -1,655 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Infrastructure.App.Persistence; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Infrastructure.App.Persistence.Repositories; - -/// -/// 租户账单仓储实现(EF Core)。 -/// -public sealed class TenantBillingRepository(TakeoutAppDbContext context, ITenantContextAccessor tenantContextAccessor) : ITenantBillingRepository -{ - private long GetCurrentTenantId() - => tenantContextAccessor.Current?.TenantId ?? 0; - - private Task> GetActiveTenantIdsAsync(CancellationToken cancellationToken) - => context.Tenants - .AsNoTracking() - .Where(x => x.DeletedAt == null && x.Id > 0) - .Select(x => x.Id) - .ToListAsync(cancellationToken); - - /// - public async Task> SearchAsync( - long tenantId, - TenantBillingStatus? status, - DateTime? from, - DateTime? to, - CancellationToken cancellationToken = default) - { - // 1. 构建基础查询:在当前租户上下文内查询 - var query = context.TenantBillingStatements - .AsNoTracking() - .Where(x => x.DeletedAt == null && x.TenantId == tenantId); - - // 2. 按状态过滤 - if (status.HasValue) - { - query = query.Where(x => x.Status == status.Value); - } - - // 3. 按日期范围过滤(账单周期) - if (from.HasValue) - { - query = query.Where(x => x.PeriodStart >= from.Value); - } - - if (to.HasValue) - { - query = query.Where(x => x.PeriodEnd <= to.Value); - } - - // 4. 排序返回 - return await query - .OrderByDescending(x => x.PeriodEnd) - .ToListAsync(cancellationToken); - } - - /// - public Task FindByIdAsync(long tenantId, long billingId, CancellationToken cancellationToken = default) - { - return context.TenantBillingStatements - .AsNoTracking() - .FirstOrDefaultAsync(x => x.DeletedAt == null && x.TenantId == tenantId && x.Id == billingId, cancellationToken); - } - - /// - public Task FindByStatementNoAsync(long tenantId, string statementNo, CancellationToken cancellationToken = default) - { - var normalized = statementNo.Trim(); - - return context.TenantBillingStatements - .AsNoTracking() - .FirstOrDefaultAsync(x => x.DeletedAt == null && x.TenantId == tenantId && x.StatementNo == normalized, cancellationToken); - } - - /// - public Task GetByStatementNoAsync(string statementNo, CancellationToken cancellationToken = default) - { - var normalized = statementNo.Trim(); - - return GetCurrentTenantId() == 0 - ? GetByStatementNoCrossTenantAsync(normalized, cancellationToken) - : context.TenantBillingStatements - .AsNoTracking() - .FirstOrDefaultAsync(x => x.DeletedAt == null && x.StatementNo == normalized, cancellationToken); - } - - /// - public Task ExistsNotCancelledByPeriodStartAsync( - long tenantId, - DateTime periodStart, - CancellationToken cancellationToken = default) - { - return context.TenantBillingStatements - .AsNoTracking() - .AnyAsync( - x => x.DeletedAt == null - && x.TenantId == tenantId - && x.PeriodStart == periodStart - && x.Status != TenantBillingStatus.Cancelled, - cancellationToken); - } - - /// - public async Task> GetOverdueBillingsAsync(CancellationToken cancellationToken = default) - { - // 1. 以当前 UTC 时间作为逾期判断基准 - var now = DateTime.UtcNow; - var currentTenantId = GetCurrentTenantId(); - if (currentTenantId != 0) - { - // 2. (空行后) 当前租户:仅查询本租户逾期账单 - return await context.TenantBillingStatements - .AsNoTracking() - .Where(x => x.DeletedAt == null - && x.DueDate < now - && x.Status == TenantBillingStatus.Pending) - .OrderBy(x => x.DueDate) - .ToListAsync(cancellationToken); - } - - // 2. (空行后) 系统上下文:逐租户查询逾期账单并合并 - var tenantIds = await GetActiveTenantIdsAsync(cancellationToken); - if (tenantIds.Count == 0) - { - return Array.Empty(); - } - - var results = new List(); - foreach (var tenantId in tenantIds) - { - using (tenantContextAccessor.EnterTenantScope(tenantId, "billing")) - { - var items = await context.TenantBillingStatements - .AsNoTracking() - .Where(x => x.DeletedAt == null - && x.DueDate < now - && x.Status == TenantBillingStatus.Pending) - .ToListAsync(cancellationToken); - - results.AddRange(items); - } - } - - return results - .OrderBy(x => x.DueDate) - .ToList(); - } - - /// - public async Task> GetBillingsDueSoonAsync(int daysAhead, CancellationToken cancellationToken = default) - { - // 1. 计算到期窗口 - var now = DateTime.UtcNow; - var dueTo = now.AddDays(daysAhead); - var currentTenantId = GetCurrentTenantId(); - if (currentTenantId != 0) - { - // 2. (空行后) 当前租户:仅查询本租户即将到期账单 - return await context.TenantBillingStatements - .AsNoTracking() - .Where(x => x.DeletedAt == null - && x.Status == TenantBillingStatus.Pending - && x.DueDate >= now - && x.DueDate <= dueTo) - .OrderBy(x => x.DueDate) - .ToListAsync(cancellationToken); - } - - // 2. (空行后) 系统上下文:逐租户查询即将到期账单并合并 - var tenantIds = await GetActiveTenantIdsAsync(cancellationToken); - if (tenantIds.Count == 0) - { - return Array.Empty(); - } - - var results = new List(); - foreach (var tenantId in tenantIds) - { - using (tenantContextAccessor.EnterTenantScope(tenantId, "billing")) - { - var items = await context.TenantBillingStatements - .AsNoTracking() - .Where(x => x.DeletedAt == null - && x.Status == TenantBillingStatus.Pending - && x.DueDate >= now - && x.DueDate <= dueTo) - .ToListAsync(cancellationToken); - - results.AddRange(items); - } - } - - return results - .OrderBy(x => x.DueDate) - .ToList(); - } - - /// - public async Task> GetByTenantIdAsync(long tenantId, CancellationToken cancellationToken = default) - { - return await context.TenantBillingStatements - .AsNoTracking() - .Where(x => x.DeletedAt == null && x.TenantId == tenantId) - .OrderByDescending(x => x.PeriodEnd) - .ToListAsync(cancellationToken); - } - - /// - public async Task> GetByIdsAsync(IReadOnlyCollection billingIds, CancellationToken cancellationToken = default) - { - if (billingIds.Count == 0) - { - return Array.Empty(); - } - - // 1. 系统上下文:逐租户查找匹配账单;租户上下文:仅返回本租户账单 - var ids = billingIds.Distinct().ToArray(); - var currentTenantId = GetCurrentTenantId(); - if (currentTenantId != 0) - { - return await context.TenantBillingStatements - .AsNoTracking() - .Where(x => x.DeletedAt == null && ids.Contains(x.Id)) - .OrderByDescending(x => x.PeriodStart) - .ToListAsync(cancellationToken); - } - - var tenantIds = await GetActiveTenantIdsAsync(cancellationToken); - if (tenantIds.Count == 0) - { - return Array.Empty(); - } - - var results = new List(); - foreach (var tenantId in tenantIds) - { - using (tenantContextAccessor.EnterTenantScope(tenantId, "billing")) - { - var items = await context.TenantBillingStatements - .AsNoTracking() - .Where(x => x.DeletedAt == null && ids.Contains(x.Id)) - .ToListAsync(cancellationToken); - - results.AddRange(items); - } - } - - return results - .OrderByDescending(x => x.PeriodStart) - .ToList(); - } - - /// - public Task AddAsync(TenantBillingStatement bill, CancellationToken cancellationToken = default) - { - return context.TenantBillingStatements.AddAsync(bill, cancellationToken).AsTask(); - } - - /// - public Task UpdateAsync(TenantBillingStatement bill, CancellationToken cancellationToken = default) - { - context.TenantBillingStatements.Update(bill); - return Task.CompletedTask; - } - - /// - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - { - return context.SaveChangesAsync(cancellationToken); - } - - /// - public async Task<(IReadOnlyList Items, int Total)> SearchPagedAsync( - long? tenantId, - TenantBillingStatus? status, - DateTime? from, - DateTime? to, - decimal? minAmount, - decimal? maxAmount, - string? keyword, - int pageNumber, - int pageSize, - CancellationToken cancellationToken = default) - { - var normalizedPageNumber = pageNumber <= 0 ? 1 : pageNumber; - var normalizedPageSize = pageSize <= 0 ? 20 : pageSize; - var skip = (normalizedPageNumber - 1) * normalizedPageSize; - var takePerTenant = normalizedPageNumber * normalizedPageSize; - - var currentTenantId = GetCurrentTenantId(); - if (currentTenantId != 0) - { - // 1. 当前租户:仅查询本租户数据(tenantId 为空则默认当前租户) - var effectiveTenantId = tenantId ?? currentTenantId; - var query = BuildTenantQuery(effectiveTenantId, status, from, to, minAmount, maxAmount, keyword); - var total = await query.CountAsync(cancellationToken); - var items = await query - .OrderByDescending(x => x.PeriodEnd) - .Skip(skip) - .Take(normalizedPageSize) - .ToListAsync(cancellationToken); - - return (items, total); - } - - // 2. (空行后) 系统上下文:可按指定 tenantId 查询;tenantId 为空则跨租户聚合分页 - if (tenantId.HasValue) - { - using (tenantContextAccessor.EnterTenantScope(tenantId.Value, "billing")) - { - var query = BuildTenantQuery(tenantId.Value, status, from, to, minAmount, maxAmount, keyword); - var total = await query.CountAsync(cancellationToken); - var items = await query - .OrderByDescending(x => x.PeriodEnd) - .Skip(skip) - .Take(normalizedPageSize) - .ToListAsync(cancellationToken); - - return (items, total); - } - } - - // 3. (空行后) 跨租户分页:逐租户取 Top(N) 后合并排序再分页 - var normalizedKeyword = string.IsNullOrWhiteSpace(keyword) ? null : keyword.Trim(); - var tenantIds = await GetActiveTenantIdsAsync(cancellationToken); - if (tenantIds.Count == 0) - { - return ([], 0); - } - - HashSet? keywordMatchedTenantIds = null; - if (!string.IsNullOrWhiteSpace(normalizedKeyword)) - { - var matched = await context.Tenants - .AsNoTracking() - .Where(x => x.DeletedAt == null && EF.Functions.ILike(x.Name, $"%{normalizedKeyword}%")) - .Select(x => x.Id) - .ToListAsync(cancellationToken); - - keywordMatchedTenantIds = matched.Count == 0 ? null : matched.ToHashSet(); - } - - var totalCount = 0; - var collected = new List(); - foreach (var tid in tenantIds) - { - using (tenantContextAccessor.EnterTenantScope(tid, "billing")) - { - var tenantQuery = BuildTenantQuery(tid, status, from, to, minAmount, maxAmount, keyword: null); - - if (!string.IsNullOrWhiteSpace(normalizedKeyword)) - { - // 3.1 租户名命中时视为匹配全部账单,否则按账单号筛选 - var tenantNameMatched = keywordMatchedTenantIds is not null && keywordMatchedTenantIds.Contains(tid); - if (!tenantNameMatched) - { - tenantQuery = tenantQuery.Where(x => EF.Functions.ILike(x.StatementNo, $"%{normalizedKeyword}%")); - } - } - - totalCount += await tenantQuery.CountAsync(cancellationToken); - - var topItems = await tenantQuery - .OrderByDescending(x => x.PeriodEnd) - .Take(takePerTenant) - .ToListAsync(cancellationToken); - - collected.AddRange(topItems); - } - } - - var pageItems = collected - .OrderByDescending(x => x.PeriodEnd) - .Skip(skip) - .Take(normalizedPageSize) - .ToList(); - - return (pageItems, totalCount); - } - - /// - public async Task GetStatisticsAsync( - long? tenantId, - DateTime startDate, - DateTime endDate, - string groupBy, - CancellationToken cancellationToken = default) - { - // 1. 统一时间基准与分组方式 - var now = DateTime.UtcNow; - var normalizedGroupBy = NormalizeGroupBy(groupBy); - var currentTenantId = GetCurrentTenantId(); - - // 2. (空行后) 构造待统计租户列表 - List targetTenantIds; - if (currentTenantId != 0) - { - targetTenantIds = [tenantId ?? currentTenantId]; - } - else if (tenantId.HasValue) - { - targetTenantIds = [tenantId.Value]; - } - else - { - targetTenantIds = await GetActiveTenantIdsAsync(cancellationToken); - } - - if (targetTenantIds.Count == 0) - { - return new TenantBillingStatistics(); - } - - // 3. (空行后) 拉取统计字段(逐租户上下文执行) - var rows = new List(); - foreach (var tid in targetTenantIds) - { - if (currentTenantId == 0) - { - using (tenantContextAccessor.EnterTenantScope(tid, "billing")) - { - var tenantRows = await BuildStatisticsQuery(startDate, endDate) - .Select(x => new BillingStatisticsRow - { - PeriodStart = x.PeriodStart, - AmountDue = x.AmountDue, - DiscountAmount = x.DiscountAmount, - TaxAmount = x.TaxAmount, - AmountPaid = x.AmountPaid, - Status = x.Status, - DueDate = x.DueDate - }) - .ToListAsync(cancellationToken); - - rows.AddRange(tenantRows); - } - - continue; - } - - var tenantRowsDirect = await BuildStatisticsQuery(startDate, endDate) - .Where(x => x.TenantId == tid) - .Select(x => new BillingStatisticsRow - { - PeriodStart = x.PeriodStart, - AmountDue = x.AmountDue, - DiscountAmount = x.DiscountAmount, - TaxAmount = x.TaxAmount, - AmountPaid = x.AmountPaid, - Status = x.Status, - DueDate = x.DueDate - }) - .ToListAsync(cancellationToken); - - rows.AddRange(tenantRowsDirect); - } - - // 4. (空行后) 汇总统计 - var totalAmount = rows.Sum(x => x.AmountDue - x.DiscountAmount + x.TaxAmount); - var paidAmount = rows.Where(x => x.Status == TenantBillingStatus.Paid).Sum(x => x.AmountPaid); - var unpaidAmount = rows.Sum(x => (x.AmountDue - x.DiscountAmount + x.TaxAmount) - x.AmountPaid); - var overdueAmount = rows - .Where(x => (x.Status == TenantBillingStatus.Pending || x.Status == TenantBillingStatus.Overdue) && x.DueDate < now) - .Sum(x => (x.AmountDue - x.DiscountAmount + x.TaxAmount) - x.AmountPaid); - - var totalCount = rows.Count; - var paidCount = rows.Count(x => x.Status == TenantBillingStatus.Paid); - var unpaidCount = rows.Count(x => x.Status == TenantBillingStatus.Pending || x.Status == TenantBillingStatus.Overdue); - var overdueCount = rows.Count(x => (x.Status == TenantBillingStatus.Pending || x.Status == TenantBillingStatus.Overdue) && x.DueDate < now); - - // 5. (空行后) 趋势统计 - var trend = rows - .GroupBy(x => GetTrendBucket(x.PeriodStart, normalizedGroupBy)) - .Select(g => new TenantBillingTrendDataPoint - { - Period = g.Key, - Count = g.Count(), - TotalAmount = g.Sum(x => x.AmountDue - x.DiscountAmount + x.TaxAmount), - PaidAmount = g.Sum(x => x.AmountPaid) - }) - .OrderBy(x => x.Period) - .ToList(); - - return new TenantBillingStatistics - { - TotalAmount = totalAmount, - PaidAmount = paidAmount, - UnpaidAmount = unpaidAmount, - OverdueAmount = overdueAmount, - TotalCount = totalCount, - PaidCount = paidCount, - UnpaidCount = unpaidCount, - OverdueCount = overdueCount, - TrendData = trend - }; - } - - /// - public Task FindByIdAsync(long billingId, CancellationToken cancellationToken = default) - { - return GetCurrentTenantId() == 0 - ? FindByIdCrossTenantAsync(billingId, cancellationToken) - : context.TenantBillingStatements - .AsNoTracking() - .FirstOrDefaultAsync(x => x.DeletedAt == null && x.Id == billingId, cancellationToken); - } - - private IQueryable BuildTenantQuery( - long tenantId, - TenantBillingStatus? status, - DateTime? from, - DateTime? to, - decimal? minAmount, - decimal? maxAmount, - string? keyword) - { - var query = context.TenantBillingStatements - .AsNoTracking() - .Where(x => x.DeletedAt == null && x.TenantId == tenantId); - - if (status.HasValue) - { - query = query.Where(x => x.Status == status.Value); - } - - if (from.HasValue) - { - query = query.Where(x => x.PeriodStart >= from.Value); - } - - if (to.HasValue) - { - query = query.Where(x => x.PeriodEnd <= to.Value); - } - - if (minAmount.HasValue) - { - query = query.Where(x => x.AmountDue >= minAmount.Value); - } - - if (maxAmount.HasValue) - { - query = query.Where(x => x.AmountDue <= maxAmount.Value); - } - - if (!string.IsNullOrWhiteSpace(keyword)) - { - var normalized = keyword.Trim(); - query = query.Where(x => EF.Functions.ILike(x.StatementNo, $"%{normalized}%")); - } - - return query; - } - - private IQueryable BuildStatisticsQuery(DateTime startDate, DateTime endDate) - => context.TenantBillingStatements - .AsNoTracking() - .Where(x => x.DeletedAt == null - && x.PeriodStart >= startDate - && x.PeriodEnd <= endDate); - - private async Task FindByIdCrossTenantAsync(long billingId, CancellationToken cancellationToken) - { - var tenantIds = await GetActiveTenantIdsAsync(cancellationToken); - foreach (var tenantId in tenantIds) - { - using (tenantContextAccessor.EnterTenantScope(tenantId, "billing")) - { - var billing = await context.TenantBillingStatements - .AsNoTracking() - .FirstOrDefaultAsync(x => x.DeletedAt == null && x.Id == billingId, cancellationToken); - if (billing != null) - { - return billing; - } - } - } - - return null; - } - - private async Task GetByStatementNoCrossTenantAsync(string statementNo, CancellationToken cancellationToken) - { - var tenantIds = await GetActiveTenantIdsAsync(cancellationToken); - foreach (var tenantId in tenantIds) - { - using (tenantContextAccessor.EnterTenantScope(tenantId, "billing")) - { - var billing = await context.TenantBillingStatements - .AsNoTracking() - .FirstOrDefaultAsync(x => x.DeletedAt == null && x.StatementNo == statementNo, cancellationToken); - if (billing != null) - { - return billing; - } - } - } - - return null; - } - - private sealed record BillingStatisticsRow - { - public required DateTime PeriodStart { get; init; } - - public required decimal AmountDue { get; init; } - - public required decimal DiscountAmount { get; init; } - - public required decimal TaxAmount { get; init; } - - public required decimal AmountPaid { get; init; } - - public required TenantBillingStatus Status { get; init; } - - public required DateTime DueDate { get; init; } - } - - private static string NormalizeGroupBy(string groupBy) - { - return groupBy.Trim() switch - { - "Week" => "Week", - "Month" => "Month", - _ => "Day" - }; - } - - private static DateTime GetTrendBucket(DateTime periodStart, string groupBy) - { - var date = periodStart.Date; - - return groupBy switch - { - "Month" => new DateTime(date.Year, date.Month, 1, 0, 0, 0, DateTimeKind.Utc), - "Week" => GetWeekStart(date), - _ => new DateTime(date.Year, date.Month, date.Day, 0, 0, 0, DateTimeKind.Utc) - }; - } - - private static DateTime GetWeekStart(DateTime date) - { - // 1. 将周一作为一周起始(与 PostgreSQL date_trunc('week', ...) 对齐) - var dayOfWeek = (int)date.DayOfWeek; // Sunday=0, Monday=1, ... - var daysSinceMonday = (dayOfWeek + 6) % 7; - - // 2. 回退到周一 00:00:00(UTC) - var monday = date.AddDays(-daysSinceMonday); - return new DateTime(monday.Year, monday.Month, monday.Day, 0, 0, 0, DateTimeKind.Utc); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/Repositories/TenantPaymentRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/Repositories/TenantPaymentRepository.cs deleted file mode 100644 index 3258722..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/Repositories/TenantPaymentRepository.cs +++ /dev/null @@ -1,105 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Infrastructure.App.Persistence; - -namespace TakeoutSaaS.Infrastructure.App.Persistence.Repositories; - -/// -/// 租户支付记录仓储实现(EF Core)。 -/// -public sealed class TenantPaymentRepository(TakeoutAppDbContext context) : ITenantPaymentRepository -{ - /// - public async Task<(IReadOnlyList Items, int Total)> SearchPagedAsync( - long tenantId, - DateTime from, - DateTime to, - int page, - int pageSize, - CancellationToken cancellationToken = default) - { - // 1. 归一化分页参数 - var normalizedPage = page <= 0 ? 1 : page; - var normalizedPageSize = pageSize <= 0 ? 20 : pageSize; - - // 2. 构建查询(按支付时间倒序) - var query = context.TenantPayments - .AsNoTracking() - .Where(x => x.DeletedAt == null - && x.TenantId == tenantId - && (x.PaidAt ?? x.CreatedAt) >= from - && (x.PaidAt ?? x.CreatedAt) <= to); - - // 3. 执行分页 - var total = await query.CountAsync(cancellationToken); - var items = await query - .OrderByDescending(x => x.PaidAt ?? x.CreatedAt) - .Skip((normalizedPage - 1) * normalizedPageSize) - .Take(normalizedPageSize) - .ToListAsync(cancellationToken); - - // 4. 返回分页结果 - return (items, total); - } - - /// - public async Task> GetByBillingIdAsync(long billingStatementId, CancellationToken cancellationToken = default) - { - return await context.TenantPayments - .AsNoTracking() - .Where(x => x.DeletedAt == null && x.BillingStatementId == billingStatementId) - .OrderByDescending(x => x.CreatedAt) - .ToListAsync(cancellationToken); - } - - /// - public async Task GetTotalPaidAmountAsync(long billingStatementId, CancellationToken cancellationToken = default) - { - // 1. 仅统计支付成功的记录 - return await context.TenantPayments - .AsNoTracking() - .Where(x => x.DeletedAt == null - && x.BillingStatementId == billingStatementId - && x.Status == TenantPaymentStatus.Success) - .SumAsync(x => x.Amount, cancellationToken); - } - - /// - public Task FindByIdAsync(long paymentId, CancellationToken cancellationToken = default) - { - return context.TenantPayments - .AsNoTracking() - .FirstOrDefaultAsync(x => x.DeletedAt == null && x.Id == paymentId, cancellationToken); - } - - /// - public Task GetByTransactionNoAsync(string transactionNo, CancellationToken cancellationToken = default) - { - var normalized = transactionNo.Trim(); - - return context.TenantPayments - .AsNoTracking() - .FirstOrDefaultAsync(x => x.DeletedAt == null && x.TransactionNo == normalized, cancellationToken); - } - - /// - public Task AddAsync(TenantPayment payment, CancellationToken cancellationToken = default) - { - return context.TenantPayments.AddAsync(payment, cancellationToken).AsTask(); - } - - /// - public Task UpdateAsync(TenantPayment payment, CancellationToken cancellationToken = default) - { - context.TenantPayments.Update(payment); - return Task.CompletedTask; - } - - /// - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - { - return context.SaveChangesAsync(cancellationToken); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/Repositories/TenantVisibilityRoleRuleRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/Repositories/TenantVisibilityRoleRuleRepository.cs deleted file mode 100644 index 398bf1c..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/Repositories/TenantVisibilityRoleRuleRepository.cs +++ /dev/null @@ -1,58 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Infrastructure.App.Persistence; - -namespace TakeoutSaaS.Infrastructure.App.Persistence.Repositories; - -/// -/// 租户可见角色规则仓储实现。 -/// -public sealed class TenantVisibilityRoleRuleRepository(TakeoutAppDbContext context) : ITenantVisibilityRoleRuleRepository -{ - /// - /// 按租户获取规则。 - /// - /// 租户 ID。 - /// 取消标记。 - /// 规则实体或 null。 - public Task FindByTenantIdAsync(long tenantId, CancellationToken cancellationToken = default) - { - return context.TenantVisibilityRoleRules - .AsNoTracking() - .FirstOrDefaultAsync(x => x.TenantId == tenantId && x.DeletedAt == null, cancellationToken); - } - - /// - /// 新增规则。 - /// - /// 规则实体。 - /// 取消标记。 - /// 异步任务。 - public Task AddAsync(TenantVisibilityRoleRule rule, CancellationToken cancellationToken = default) - { - return context.TenantVisibilityRoleRules.AddAsync(rule, cancellationToken).AsTask(); - } - - /// - /// 更新规则。 - /// - /// 规则实体。 - /// 取消标记。 - /// 异步任务。 - public Task UpdateAsync(TenantVisibilityRoleRule rule, CancellationToken cancellationToken = default) - { - context.TenantVisibilityRoleRules.Update(rule); - return Task.CompletedTask; - } - - /// - /// 保存变更。 - /// - /// 取消标记。 - /// 异步任务。 - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - { - return context.SaveChangesAsync(cancellationToken); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/TakeoutAppDbContext.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/TakeoutAppDbContext.cs deleted file mode 100644 index f1c8126..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/TakeoutAppDbContext.cs +++ /dev/null @@ -1,1556 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; -using TakeoutSaaS.Domain.Analytics.Entities; -using TakeoutSaaS.Domain.Coupons.Entities; -using TakeoutSaaS.Domain.CustomerService.Entities; -using TakeoutSaaS.Domain.Deliveries.Entities; -using TakeoutSaaS.Domain.Distribution.Entities; -using TakeoutSaaS.Domain.Engagement.Entities; -using TakeoutSaaS.Domain.GroupBuying.Entities; -using TakeoutSaaS.Domain.Inventory.Entities; -using TakeoutSaaS.Domain.Membership.Entities; -using TakeoutSaaS.Domain.Merchants.Entities; -using TakeoutSaaS.Domain.Navigation.Entities; -using TakeoutSaaS.Domain.Ordering.Entities; -using TakeoutSaaS.Domain.Orders.Entities; -using TakeoutSaaS.Domain.Payments.Entities; -using TakeoutSaaS.Domain.Products.Entities; -using TakeoutSaaS.Domain.Queues.Entities; -using TakeoutSaaS.Domain.Reservations.Entities; -using TakeoutSaaS.Domain.Stores.Entities; -using TakeoutSaaS.Domain.Stores.Enums; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Infrastructure.Common.Persistence; -using TakeoutSaaS.Shared.Abstractions.Ids; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; -using TakeoutSaaS.Infrastructure.App.Persistence.Configurations; - -namespace TakeoutSaaS.Infrastructure.App.Persistence; - -/// -/// 业务主库 DbContext。 -/// -public sealed class TakeoutAppDbContext( - DbContextOptions options, - ITenantProvider tenantProvider, - ICurrentUserAccessor? currentUserAccessor = null, - IIdGenerator? idGenerator = null) - : TenantAwareDbContext(options, tenantProvider, currentUserAccessor, idGenerator) -{ - /// - /// 租户聚合根。 - /// - public DbSet Tenants => Set(); - /// - /// 租户套餐。 - /// - public DbSet TenantPackages => Set(); - /// - /// 租户订阅。 - /// - public DbSet TenantSubscriptions => Set(); - /// - /// 租户订阅历史。 - /// - public DbSet TenantSubscriptionHistories => Set(); - /// - /// 租户配额使用记录。 - /// - public DbSet TenantQuotaUsages => Set(); - /// - /// 租户配额使用历史记录。 - /// - public DbSet TenantQuotaUsageHistories => Set(); - /// - /// 租户账单。 - /// - public DbSet TenantBillingStatements => Set(); - /// - /// 租户支付记录。 - /// - public DbSet TenantPayments => Set(); - /// - /// 租户通知。 - /// - public DbSet TenantNotifications => Set(); - /// - /// 租户公告。 - /// - public DbSet TenantAnnouncements => Set(); - /// - /// 租户公告已读记录。 - /// - public DbSet TenantAnnouncementReads => Set(); - /// - /// 租户认证资料。 - /// - public DbSet TenantVerificationProfiles => Set(); - /// - /// 租户账单/配额可见角色规则。 - /// - public DbSet TenantVisibilityRoleRules => Set(); - /// - /// 配额包定义。 - /// - public DbSet QuotaPackages => Set(); - /// - /// 租户配额包购买记录。 - /// - public DbSet TenantQuotaPackagePurchases => Set(); - /// - /// 商户实体。 - /// - public DbSet Merchants => Set(); - /// - /// 商户资质文件。 - /// - public DbSet MerchantDocuments => Set(); - /// - /// 商户合同。 - /// - public DbSet MerchantContracts => Set(); - /// - /// 商户员工。 - /// - public DbSet MerchantStaff => Set(); - /// - /// 商户分类。 - /// - public DbSet MerchantCategories => Set(); - /// - /// 门店实体。 - /// - public DbSet Stores => Set(); - /// - /// 门店费用配置。 - /// - public DbSet StoreFees => Set(); - /// - /// 门店资质证照。 - /// - public DbSet StoreQualifications => Set(); - /// - /// 门店审核记录。 - /// - public DbSet StoreAuditRecords => Set(); - /// - /// 门店营业时间。 - /// - public DbSet StoreBusinessHours => Set(); - /// - /// 门店节假日。 - /// - public DbSet StoreHolidays => Set(); - /// - /// 门店配送区域。 - /// - public DbSet StoreDeliveryZones => Set(); - /// - /// 门店桌台区域。 - /// - public DbSet StoreTableAreas => Set(); - /// - /// 门店桌台。 - /// - public DbSet StoreTables => Set(); - /// - /// 门店员工班次。 - /// - public DbSet StoreEmployeeShifts => Set(); - /// - /// 自提配置。 - /// - public DbSet StorePickupSettings => Set(); - /// - /// 自提时间段。 - /// - public DbSet StorePickupSlots => Set(); - /// - /// 商品分类。 - /// - public DbSet ProductCategories => Set(); - /// - /// 商品。 - /// - public DbSet Products => Set(); - /// - /// 商品属性组。 - /// - public DbSet ProductAttributeGroups => Set(); - /// - /// 商品属性项。 - /// - public DbSet ProductAttributeOptions => Set(); - /// - /// SKU 实体。 - /// - public DbSet ProductSkus => Set(); - /// - /// 加料分组。 - /// - public DbSet ProductAddonGroups => Set(); - /// - /// 加料选项。 - /// - public DbSet ProductAddonOptions => Set(); - /// - /// 定价规则。 - /// - public DbSet ProductPricingRules => Set(); - /// - /// 商品媒体资源。 - /// - public DbSet ProductMediaAssets => Set(); - /// - /// 库存项目。 - /// - public DbSet InventoryItems => Set(); - /// - /// 库存调整记录。 - /// - public DbSet InventoryAdjustments => Set(); - /// - /// 库存批次。 - /// - public DbSet InventoryBatches => Set(); - /// - /// 库存锁定记录。 - /// - public DbSet InventoryLockRecords => Set(); - /// - /// 购物车。 - /// - public DbSet ShoppingCarts => Set(); - /// - /// 购物车明细。 - /// - public DbSet CartItems => Set(); - /// - /// 购物车加料。 - /// - public DbSet CartItemAddons => Set(); - /// - /// 结账会话。 - /// - public DbSet CheckoutSessions => Set(); - /// - /// 订单聚合。 - /// - public DbSet Orders => Set(); - /// - /// 订单明细。 - /// - public DbSet OrderItems => Set(); - /// - /// 订单状态流转。 - /// - public DbSet OrderStatusHistories => Set(); - /// - /// 退款申请。 - /// - public DbSet RefundRequests => Set(); - /// - /// 支付记录。 - /// - public DbSet PaymentRecords => Set(); - /// - /// 支付退款记录。 - /// - public DbSet PaymentRefundRecords => Set(); - /// - /// 预订记录。 - /// - public DbSet Reservations => Set(); - /// - /// 排号记录。 - /// - public DbSet QueueTickets => Set(); - /// - /// 配送订单。 - /// - public DbSet DeliveryOrders => Set(); - /// - /// 配送事件。 - /// - public DbSet DeliveryEvents => Set(); - /// - /// 团购订单。 - /// - public DbSet GroupOrders => Set(); - /// - /// 团购参与者。 - /// - public DbSet GroupParticipants => Set(); - /// - /// 优惠券模板。 - /// - public DbSet CouponTemplates => Set(); - /// - /// 优惠券实例。 - /// - public DbSet Coupons => Set(); - /// - /// 营销活动。 - /// - public DbSet PromotionCampaigns => Set(); - /// - /// 会员档案。 - /// - public DbSet MemberProfiles => Set(); - /// - /// 会员等级。 - /// - public DbSet MemberTiers => Set(); - /// - /// 积分流水。 - /// - public DbSet MemberPointLedgers => Set(); - /// - /// 会话记录。 - /// - public DbSet ChatSessions => Set(); - /// - /// 会话消息。 - /// - public DbSet ChatMessages => Set(); - /// - /// 工单记录。 - /// - public DbSet SupportTickets => Set(); - /// - /// 工单评论。 - /// - public DbSet TicketComments => Set(); - /// - /// 分销合作伙伴。 - /// - public DbSet AffiliatePartners => Set(); - /// - /// 分销订单。 - /// - public DbSet AffiliateOrders => Set(); - /// - /// 分销结算。 - /// - public DbSet AffiliatePayouts => Set(); - /// - /// 打卡活动。 - /// - public DbSet CheckInCampaigns => Set(); - /// - /// 打卡记录。 - /// - public DbSet CheckInRecords => Set(); - /// - /// 社区帖子。 - /// - public DbSet CommunityPosts => Set(); - /// - /// 社区评论。 - /// - public DbSet CommunityComments => Set(); - /// - /// 社区互动。 - /// - public DbSet CommunityReactions => Set(); - /// - /// 地图位置。 - /// - public DbSet MapLocations => Set(); - /// - /// 导航请求。 - /// - public DbSet NavigationRequests => Set(); - /// - /// 指标定义。 - /// - public DbSet MetricDefinitions => Set(); - /// - /// 指标快照。 - /// - public DbSet MetricSnapshots => Set(); - /// - /// 告警规则。 - /// - public DbSet MetricAlertRules => Set(); - /// - /// 配置实体映射关系。 - /// - /// 模型构建器。 - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - // 1. 调用基类配置 - base.OnModelCreating(modelBuilder); - // 2. 配置全部实体映射 - ConfigureTenant(modelBuilder.Entity()); - ConfigureMerchant(modelBuilder.Entity()); - ConfigureStore(modelBuilder.Entity()); - ConfigureTenantPackage(modelBuilder.Entity()); - ConfigureTenantSubscription(modelBuilder.Entity()); - ConfigureTenantSubscriptionHistory(modelBuilder.Entity()); - ConfigureTenantQuotaUsage(modelBuilder.Entity()); - ConfigureTenantQuotaUsageHistory(modelBuilder.Entity()); - ConfigureTenantBilling(modelBuilder.Entity()); - ConfigureTenantPayment(modelBuilder.Entity()); - ConfigureTenantNotification(modelBuilder.Entity()); - ConfigureTenantAnnouncement(modelBuilder.Entity()); - ConfigureTenantAnnouncementRead(modelBuilder.Entity()); - ConfigureTenantVerificationProfile(modelBuilder.Entity()); - ConfigureTenantVisibilityRoleRule(modelBuilder.Entity()); - ConfigureQuotaPackage(modelBuilder.Entity()); - ConfigureTenantQuotaPackagePurchase(modelBuilder.Entity()); - ConfigureMerchantDocument(modelBuilder.Entity()); - ConfigureMerchantContract(modelBuilder.Entity()); - ConfigureMerchantStaff(modelBuilder.Entity()); - ConfigureMerchantCategory(modelBuilder.Entity()); - ConfigureStoreFee(modelBuilder.Entity()); - ConfigureStoreQualification(modelBuilder.Entity()); - ConfigureStoreAuditRecord(modelBuilder.Entity()); - ConfigureStoreBusinessHour(modelBuilder.Entity()); - ConfigureStoreHoliday(modelBuilder.Entity()); - ConfigureStoreDeliveryZone(modelBuilder.Entity()); - ConfigureStoreTableArea(modelBuilder.Entity()); - ConfigureStoreTable(modelBuilder.Entity()); - ConfigureStoreEmployeeShift(modelBuilder.Entity()); - ConfigureStorePickupSetting(modelBuilder.Entity()); - ConfigureStorePickupSlot(modelBuilder.Entity()); - ConfigureProductCategory(modelBuilder.Entity()); - ConfigureProduct(modelBuilder.Entity()); - ConfigureProductAttributeGroup(modelBuilder.Entity()); - ConfigureProductAttributeOption(modelBuilder.Entity()); - ConfigureProductSku(modelBuilder.Entity()); - ConfigureProductAddonGroup(modelBuilder.Entity()); - ConfigureProductAddonOption(modelBuilder.Entity()); - ConfigureProductPricingRule(modelBuilder.Entity()); - ConfigureProductMediaAsset(modelBuilder.Entity()); - ConfigureInventoryItem(modelBuilder.Entity()); - ConfigureInventoryAdjustment(modelBuilder.Entity()); - ConfigureInventoryBatch(modelBuilder.Entity()); - ConfigureInventoryLockRecord(modelBuilder.Entity()); - ConfigureShoppingCart(modelBuilder.Entity()); - ConfigureCartItem(modelBuilder.Entity()); - ConfigureCartItemAddon(modelBuilder.Entity()); - ConfigureCheckoutSession(modelBuilder.Entity()); - ConfigureOrder(modelBuilder.Entity()); - ConfigureOrderItem(modelBuilder.Entity()); - ConfigureOrderStatusHistory(modelBuilder.Entity()); - ConfigureRefundRequest(modelBuilder.Entity()); - ConfigurePaymentRecord(modelBuilder.Entity()); - ConfigurePaymentRefundRecord(modelBuilder.Entity()); - ConfigureReservation(modelBuilder.Entity()); - ConfigureQueueTicket(modelBuilder.Entity()); - ConfigureDelivery(modelBuilder.Entity()); - ConfigureDeliveryEvent(modelBuilder.Entity()); - ConfigureGroupOrder(modelBuilder.Entity()); - ConfigureGroupParticipant(modelBuilder.Entity()); - ConfigureCouponTemplate(modelBuilder.Entity()); - ConfigureCoupon(modelBuilder.Entity()); - ConfigurePromotionCampaign(modelBuilder.Entity()); - ConfigureMemberProfile(modelBuilder.Entity()); - ConfigureMemberTier(modelBuilder.Entity()); - ConfigureMemberPointLedger(modelBuilder.Entity()); - ConfigureChatSession(modelBuilder.Entity()); - ConfigureChatMessage(modelBuilder.Entity()); - ConfigureSupportTicket(modelBuilder.Entity()); - ConfigureTicketComment(modelBuilder.Entity()); - ConfigureAffiliatePartner(modelBuilder.Entity()); - ConfigureAffiliateOrder(modelBuilder.Entity()); - ConfigureAffiliatePayout(modelBuilder.Entity()); - ConfigureCheckInCampaign(modelBuilder.Entity()); - ConfigureCheckInRecord(modelBuilder.Entity()); - ConfigureCommunityPost(modelBuilder.Entity()); - ConfigureCommunityComment(modelBuilder.Entity()); - ConfigureCommunityReaction(modelBuilder.Entity()); - ConfigureMapLocation(modelBuilder.Entity()); - ConfigureNavigationRequest(modelBuilder.Entity()); - ConfigureMetricDefinition(modelBuilder.Entity()); - ConfigureMetricSnapshot(modelBuilder.Entity()); - ConfigureMetricAlertRule(modelBuilder.Entity()); - - // 3. 应用多租户全局查询过滤器 - ApplyTenantQueryFilters(modelBuilder); - } - - private static void ConfigureTenant(EntityTypeBuilder builder) - { - builder.ToTable("tenants"); - builder.HasKey(x => x.Id); - builder.Property(x => x.Code).HasMaxLength(64).IsRequired(); - builder.Property(x => x.Name).HasMaxLength(128).IsRequired(); - builder.Property(x => x.ShortName).HasMaxLength(64); - builder.Property(x => x.ContactName).HasMaxLength(64); - builder.Property(x => x.ContactPhone).HasMaxLength(32); - builder.Property(x => x.ContactEmail).HasMaxLength(128); - builder.Property(x => x.Industry).HasMaxLength(64); - builder.Property(x => x.LogoUrl).HasColumnType("text"); - builder.Property(x => x.Remarks).HasMaxLength(512); - builder.Property(x => x.OperatingMode).HasConversion(); - builder.HasIndex(x => x.Code).IsUnique(); - builder.HasIndex(x => x.ContactPhone).IsUnique(); - } - - private static void ConfigureTenantVerificationProfile(EntityTypeBuilder builder) - { - builder.ToTable("tenant_verification_profiles"); - builder.HasKey(x => x.Id); - builder.Property(x => x.TenantId).IsRequired(); - builder.Property(x => x.BusinessLicenseNumber).HasMaxLength(64); - builder.Property(x => x.BusinessLicenseUrl).HasMaxLength(512); - builder.Property(x => x.LegalPersonName).HasMaxLength(64); - builder.Property(x => x.LegalPersonIdNumber).HasMaxLength(32); - builder.Property(x => x.LegalPersonIdFrontUrl).HasMaxLength(512); - builder.Property(x => x.LegalPersonIdBackUrl).HasMaxLength(512); - builder.Property(x => x.BankAccountName).HasMaxLength(128); - builder.Property(x => x.BankAccountNumber).HasMaxLength(64); - builder.Property(x => x.BankName).HasMaxLength(128); - builder.Property(x => x.ReviewRemarks).HasMaxLength(512); - builder.Property(x => x.ReviewedByName).HasMaxLength(64); - builder.HasIndex(x => x.TenantId).IsUnique(); - } - - // 租户订阅历史映射 - private static void ConfigureTenantSubscriptionHistory(EntityTypeBuilder builder) - { - builder.ToTable("tenant_subscription_histories"); - builder.HasKey(x => x.Id); - builder.Property(x => x.TenantId).IsRequired(); - builder.Property(x => x.TenantSubscriptionId).IsRequired(); - builder.Property(x => x.Notes).HasMaxLength(512); - builder.Property(x => x.Currency).HasMaxLength(8); - builder.HasIndex(x => new { x.TenantId, x.TenantSubscriptionId }); - } - - private static void ConfigureMerchant(EntityTypeBuilder builder) - { - builder.ToTable("merchants"); - builder.HasKey(x => x.Id); - builder.Property(x => x.BrandName).HasMaxLength(128).IsRequired(); - builder.Property(x => x.BrandAlias).HasMaxLength(64); - builder.Property(x => x.LegalPerson).HasMaxLength(64); - builder.Property(x => x.BusinessLicenseNumber).HasMaxLength(64); - builder.Property(x => x.ContactPhone).HasMaxLength(32).IsRequired(); - builder.Property(x => x.ContactEmail).HasMaxLength(128); - builder.Property(x => x.Province).HasMaxLength(64); - builder.Property(x => x.City).HasMaxLength(64); - builder.Property(x => x.District).HasMaxLength(64); - builder.Property(x => x.Address).HasMaxLength(256); - builder.Property(x => x.ReviewRemarks).HasMaxLength(512); - builder.Property(x => x.OperatingMode).HasConversion(); - builder.Property(x => x.IsFrozen).HasDefaultValue(false); - builder.Property(x => x.FrozenReason).HasMaxLength(500); - builder.Property(x => x.ClaimedByName).HasMaxLength(100); - builder.Ignore(x => x.RowVersion); - builder.Property("xmin") - .HasColumnName("xmin") - .HasColumnType("xid") - .ValueGeneratedOnAddOrUpdate() - .IsConcurrencyToken(); - builder.HasIndex(x => x.TenantId); - builder.HasIndex(x => new { x.TenantId, x.Status }); - builder.HasIndex(x => x.ClaimedBy); - } - - private static void ConfigureStore(EntityTypeBuilder builder) - { - builder.ToTable("stores"); - builder.HasKey(x => x.Id); - builder.Property(x => x.Code).HasMaxLength(32).IsRequired(); - builder.Property(x => x.Name).HasMaxLength(128).IsRequired(); - builder.Property(x => x.Phone).HasMaxLength(32); - builder.Property(x => x.ManagerName).HasMaxLength(64); - builder.Property(x => x.BusinessLicenseNumber).HasMaxLength(50); - builder.Property(x => x.LegalRepresentative).HasMaxLength(100); - builder.Property(x => x.RegisteredAddress).HasMaxLength(500); - builder.Property(x => x.BusinessLicenseImageUrl).HasMaxLength(500); - builder.Property(x => x.SignboardImageUrl).HasMaxLength(500); - builder.Property(x => x.OwnershipType).HasConversion(); - builder.Property(x => x.AuditStatus).HasConversion(); - builder.Property(x => x.BusinessStatus).HasConversion(); - builder.Property(x => x.ClosureReason).HasConversion(); - builder.Property(x => x.ClosureReasonText).HasMaxLength(500); - builder.Property(x => x.RejectionReason).HasMaxLength(500); - builder.Property(x => x.ForceCloseReason).HasMaxLength(500); - builder.Property(x => x.Province).HasMaxLength(64); - builder.Property(x => x.City).HasMaxLength(64); - builder.Property(x => x.District).HasMaxLength(64); - builder.Property(x => x.Address).HasMaxLength(256); - builder.Property(x => x.BusinessHours).HasMaxLength(256); - builder.Property(x => x.Announcement).HasMaxLength(512); - builder.Property(x => x.DeliveryRadiusKm).HasPrecision(6, 2); - builder.HasIndex(x => new { x.TenantId, x.MerchantId }); - builder.HasIndex(x => new { x.TenantId, x.Code }).IsUnique(); - builder.HasIndex(x => new { x.TenantId, x.AuditStatus }); - builder.HasIndex(x => new { x.TenantId, x.BusinessStatus }); - builder.HasIndex(x => new { x.TenantId, x.OwnershipType }); - builder.HasIndex(x => new { x.Longitude, x.Latitude }) - .HasFilter("\"Longitude\" IS NOT NULL AND \"Latitude\" IS NOT NULL"); - builder.HasIndex(x => new { x.MerchantId, x.BusinessLicenseNumber }) - .IsUnique() - .HasFilter("\"BusinessLicenseNumber\" IS NOT NULL AND \"Status\" <> 3"); - } - - private static void ConfigureStoreFee(EntityTypeBuilder builder) - { - builder.ToTable("store_fees"); - builder.HasKey(x => x.Id); - builder.Property(x => x.StoreId).IsRequired(); - builder.Property(x => x.MinimumOrderAmount).HasPrecision(10, 2); - builder.Property(x => x.BaseDeliveryFee).HasPrecision(10, 2); - builder.Property(x => x.PackagingFeeMode).HasConversion(); - builder.Property(x => x.OrderPackagingFeeMode).HasConversion(); - builder.Property(x => x.FixedPackagingFee).HasPrecision(10, 2); - builder.Property(x => x.PackagingFeeTiersJson).HasColumnType("text"); - builder.Property(x => x.FreeDeliveryThreshold).HasPrecision(10, 2); - builder.HasIndex(x => new { x.TenantId, x.StoreId }).IsUnique(); - builder.HasIndex(x => x.TenantId); - } - - private static void ConfigureStoreQualification(EntityTypeBuilder builder) - { - builder.ToTable("store_qualifications"); - builder.HasKey(x => x.Id); - builder.Property(x => x.StoreId).IsRequired(); - builder.Property(x => x.QualificationType).HasConversion(); - builder.Property(x => x.FileUrl).HasMaxLength(500).IsRequired(); - builder.Property(x => x.DocumentNumber).HasMaxLength(100); - builder.Property(x => x.IssuedAt).HasColumnType("date"); - builder.Property(x => x.ExpiresAt).HasColumnType("date"); - builder.Property(x => x.SortOrder).HasDefaultValue(100); - builder.HasIndex(x => new { x.TenantId, x.StoreId }); - builder.HasIndex(x => x.ExpiresAt) - .HasFilter("\"ExpiresAt\" IS NOT NULL"); - builder.Ignore(x => x.IsExpired); - builder.Ignore(x => x.IsExpiringSoon); - } - - private static void ConfigureStoreAuditRecord(EntityTypeBuilder builder) - { - builder.ToTable("store_audit_records"); - builder.HasKey(x => x.Id); - builder.Property(x => x.StoreId).IsRequired(); - builder.Property(x => x.Action).HasConversion(); - builder.Property(x => x.PreviousStatus).HasConversion(); - builder.Property(x => x.NewStatus).HasConversion(); - builder.Property(x => x.OperatorName).HasMaxLength(100).IsRequired(); - builder.Property(x => x.RejectionReason).HasMaxLength(500); - builder.Property(x => x.Remarks).HasMaxLength(1000); - builder.HasIndex(x => new { x.TenantId, x.StoreId }); - builder.HasIndex(x => x.CreatedAt); - } - - private static void ConfigureProductCategory(EntityTypeBuilder builder) - { - builder.ToTable("product_categories"); - builder.HasKey(x => x.Id); - builder.Property(x => x.Name).HasMaxLength(64).IsRequired(); - builder.Property(x => x.Description).HasMaxLength(256); - builder.HasIndex(x => new { x.TenantId, x.StoreId }); - } - - private static void ConfigureProduct(EntityTypeBuilder builder) - { - builder.ToTable("products"); - builder.HasKey(x => x.Id); - builder.Property(x => x.SpuCode).HasMaxLength(32).IsRequired(); - builder.Property(x => x.Name).HasMaxLength(128).IsRequired(); - builder.Property(x => x.Subtitle).HasMaxLength(256); - builder.Property(x => x.Unit).HasMaxLength(16); - builder.Property(x => x.Price).HasPrecision(18, 2); - builder.Property(x => x.OriginalPrice).HasPrecision(18, 2); - builder.Property(x => x.CoverImage).HasMaxLength(256); - builder.Property(x => x.GalleryImages).HasMaxLength(1024); - builder.Property(x => x.Description).HasColumnType("text"); - builder.HasIndex(x => new { x.TenantId, x.StoreId }); - builder.HasIndex(x => new { x.TenantId, x.SpuCode }).IsUnique(); - } - - private static void ConfigureOrder(EntityTypeBuilder builder) - { - builder.ToTable("orders"); - builder.HasKey(x => x.Id); - builder.Property(x => x.OrderNo).HasMaxLength(32).IsRequired(); - builder.Property(x => x.CustomerName).HasMaxLength(64); - builder.Property(x => x.CustomerPhone).HasMaxLength(32); - builder.Property(x => x.TableNo).HasMaxLength(32); - builder.Property(x => x.QueueNumber).HasMaxLength(32); - builder.Property(x => x.CancelReason).HasMaxLength(256); - builder.Property(x => x.Remark).HasMaxLength(512); - builder.Property(x => x.ItemsAmount).HasPrecision(18, 2); - builder.Property(x => x.DiscountAmount).HasPrecision(18, 2); - builder.Property(x => x.PayableAmount).HasPrecision(18, 2); - builder.Property(x => x.PaidAmount).HasPrecision(18, 2); - builder.HasIndex(x => new { x.TenantId, x.OrderNo }).IsUnique(); - builder.HasIndex(x => new { x.TenantId, x.StoreId, x.Status }); - } - - private static void ConfigureOrderItem(EntityTypeBuilder builder) - { - builder.ToTable("order_items"); - builder.HasKey(x => x.Id); - builder.Property(x => x.ProductName).HasMaxLength(128).IsRequired(); - builder.Property(x => x.SkuName).HasMaxLength(128); - builder.Property(x => x.Unit).HasMaxLength(16); - builder.Property(x => x.UnitPrice).HasPrecision(18, 2); - builder.Property(x => x.DiscountAmount).HasPrecision(18, 2); - builder.Property(x => x.SubTotal).HasPrecision(18, 2); - builder.Property(x => x.AttributesJson).HasColumnType("text"); - builder.HasIndex(x => new { x.TenantId, x.OrderId }); - builder.HasOne() - .WithMany() - .HasForeignKey(x => x.OrderId) - .OnDelete(DeleteBehavior.Cascade); - } - - private static void ConfigurePaymentRecord(EntityTypeBuilder builder) - { - builder.ToTable("payment_records"); - builder.HasKey(x => x.Id); - builder.Property(x => x.Amount).HasPrecision(18, 2); - builder.Property(x => x.TradeNo).HasMaxLength(64); - builder.Property(x => x.ChannelTransactionId).HasMaxLength(64); - builder.Property(x => x.Remark).HasMaxLength(256); - builder.Property(x => x.Payload).HasColumnType("text"); - builder.HasIndex(x => new { x.TenantId, x.OrderId }); - } - - private static void ConfigureReservation(EntityTypeBuilder builder) - { - builder.ToTable("reservations"); - builder.HasKey(x => x.Id); - builder.Property(x => x.ReservationNo).HasMaxLength(32).IsRequired(); - builder.Property(x => x.CustomerName).HasMaxLength(64).IsRequired(); - builder.Property(x => x.CustomerPhone).HasMaxLength(32).IsRequired(); - builder.Property(x => x.TablePreference).HasMaxLength(64); - builder.Property(x => x.Remark).HasMaxLength(512); - builder.Property(x => x.CheckInCode).HasMaxLength(32); - builder.HasIndex(x => new { x.TenantId, x.StoreId }); - builder.HasIndex(x => new { x.TenantId, x.ReservationNo }).IsUnique(); - } - - private static void ConfigureQueueTicket(EntityTypeBuilder builder) - { - builder.ToTable("queue_tickets"); - builder.HasKey(x => x.Id); - builder.Property(x => x.TicketNumber).HasMaxLength(32).IsRequired(); - builder.Property(x => x.Remark).HasMaxLength(256); - builder.HasIndex(x => new { x.TenantId, x.StoreId }); - builder.HasIndex(x => new { x.TenantId, x.StoreId, x.TicketNumber }).IsUnique(); - } - - private static void ConfigureDelivery(EntityTypeBuilder builder) - { - builder.ToTable("delivery_orders"); - builder.HasKey(x => x.Id); - builder.Property(x => x.ProviderOrderId).HasMaxLength(64); - builder.Property(x => x.DeliveryFee).HasPrecision(18, 2); - builder.Property(x => x.CourierName).HasMaxLength(64); - builder.Property(x => x.CourierPhone).HasMaxLength(32); - builder.Property(x => x.FailureReason).HasMaxLength(256); - builder.HasIndex(x => new { x.TenantId, x.OrderId }).IsUnique(); - } - - private static void ConfigureTenantPackage(EntityTypeBuilder builder) - { - builder.ToTable("tenant_packages"); - builder.HasKey(x => x.Id); - builder.Property(x => x.Name).HasMaxLength(128).IsRequired(); - builder.Property(x => x.Description).HasMaxLength(512); - builder.Property(x => x.FeaturePoliciesJson).HasColumnType("text"); - builder.Property(x => x.PublishStatus) - .HasConversion() - .HasDefaultValue(TenantPackagePublishStatus.Draft) - .HasSentinel((TenantPackagePublishStatus)(-1)) - .HasComment("发布状态:0=草稿,1=已发布。"); - - // 1. 解决 EF Core 默认值哨兵问题:当我们希望插入 false/0 时,若数据库配置了 default 且 EF 认为该值是“未设置”,会导致 insert 省略列,最终落库为默认值。 - // 2. 发布状态使用 -1 作为哨兵,避免 Draft=0 被误判为“未设置”而触发数据库默认值(发布/草稿切换必须可控)。 - // 3. 将布尔开关哨兵值设置为数据库默认值:true 作为哨兵,false 才会被显式写入,从而保证“可见性/可售开关”在新增时可正确落库。 - builder.Property(x => x.IsPublicVisible) - .HasDefaultValue(true) - .HasSentinel(true) - .HasComment("是否对外可见(展示页/套餐列表可见性)。"); - builder.Property(x => x.IsAllowNewTenantPurchase) - .HasDefaultValue(true) - .HasSentinel(true) - .HasComment("是否允许新租户购买/选择(仅影响新购)。"); - - // 4. 展示配置:推荐标识与标签(用于套餐展示页/对比页) - builder.Property(x => x.IsRecommended) - .HasDefaultValue(false) - .HasComment("是否推荐展示(运营推荐标识)。"); - builder.Property(x => x.Tags) - .HasColumnType("text[]") - .HasComment("套餐标签(用于展示与对比页)。"); - builder.Property(x => x.SortOrder).HasDefaultValue(0).HasComment("展示排序,数值越小越靠前。"); - builder.HasIndex(x => new { x.IsActive, x.SortOrder }); - builder.HasIndex(x => new { x.PublishStatus, x.IsActive, x.IsPublicVisible, x.IsAllowNewTenantPurchase, x.SortOrder }); - } - - private static void ConfigureTenantSubscription(EntityTypeBuilder builder) - { - builder.ToTable("tenant_subscriptions"); - builder.HasKey(x => x.Id); - builder.Property(x => x.TenantPackageId).IsRequired(); - builder.Property(x => x.Status).HasConversion(); - builder.HasIndex(x => new { x.TenantId, x.TenantPackageId }); - } - - private static void ConfigureTenantQuotaUsage(EntityTypeBuilder builder) - { - builder.ToTable("tenant_quota_usages"); - builder.HasKey(x => x.Id); - builder.Property(x => x.QuotaType).HasConversion(); - builder.HasIndex(x => new { x.TenantId, x.QuotaType }).IsUnique(); - } - - private static void ConfigureTenantQuotaUsageHistory(EntityTypeBuilder builder) - { - builder.ToTable("tenant_quota_usage_histories"); - builder.HasKey(x => x.Id); - builder.Property(x => x.QuotaType).HasConversion(); - builder.Property(x => x.ChangeType).HasConversion(); - builder.Property(x => x.ChangeReason).HasMaxLength(256); - - builder.HasIndex(x => new { x.TenantId, x.QuotaType, x.RecordedAt }); - builder.HasIndex(x => new { x.TenantId, x.RecordedAt }); - } - - private static void ConfigureTenantBilling(EntityTypeBuilder builder) - { - new TenantBillingStatementConfiguration().Configure(builder); - } - - private static void ConfigureTenantPayment(EntityTypeBuilder builder) - { - new TenantPaymentConfiguration().Configure(builder); - } - - private static void ConfigureTenantNotification(EntityTypeBuilder builder) - { - builder.ToTable("tenant_notifications"); - builder.HasKey(x => x.Id); - builder.Property(x => x.Title).HasMaxLength(128).IsRequired(); - builder.Property(x => x.Message).HasMaxLength(1024).IsRequired(); - builder.Property(x => x.Channel).HasConversion(); - builder.Property(x => x.Severity).HasConversion(); - builder.Property(x => x.MetadataJson).HasColumnType("text"); - builder.HasIndex(x => new { x.TenantId, x.Channel, x.SentAt }); - } - - private static void ConfigureTenantVisibilityRoleRule(EntityTypeBuilder builder) - { - builder.ToTable("tenant_visibility_role_rules"); - builder.HasKey(x => x.Id); - builder.Property(x => x.TenantId).IsRequired(); - builder.Property(x => x.QuotaVisibleRoleCodes).HasColumnType("text[]"); - builder.Property(x => x.BillingVisibleRoleCodes).HasColumnType("text[]"); - builder.Property(x => x.UpdatedBy).IsRequired(); - builder.Property(x => x.UpdatedAt).IsRequired(); - builder.HasIndex(x => x.TenantId).IsUnique(); - } - - private static void ConfigureTenantAnnouncement(EntityTypeBuilder builder) - { - builder.ToTable("tenant_announcements"); - builder.HasKey(x => x.Id); - builder.Property(x => x.TenantId).IsRequired(); - builder.Property(x => x.Title).HasMaxLength(128).IsRequired(); - builder.Property(x => x.Content).HasColumnType("text").IsRequired(); - builder.Property(x => x.AnnouncementType) - .HasConversion(); - builder.Property(x => x.PublisherScope) - .HasConversion(); - builder.Property(x => x.PublisherUserId); - builder.Property(x => x.Status) - .HasConversion(); - builder.Property(x => x.PublishedAt); - builder.Property(x => x.RevokedAt); - builder.Property(x => x.ScheduledPublishAt); - builder.Property(x => x.TargetType).HasMaxLength(64).IsRequired(); - builder.Property(x => x.TargetParameters).HasColumnType("text"); - builder.Property(x => x.Priority).IsRequired(); - builder.Property("IsActive").IsRequired(); - builder.Property(x => x.RowVersion) - .IsRowVersion() - .IsConcurrencyToken() - .HasColumnType("bytea"); - ConfigureAuditableEntity(builder); - ConfigureSoftDeleteEntity(builder); - builder.HasIndex("TenantId", "AnnouncementType", "IsActive"); - builder.HasIndex(x => new { x.TenantId, x.EffectiveFrom, x.EffectiveTo }); - builder.HasIndex(x => new { x.TenantId, x.Status, x.EffectiveFrom }); - builder.HasIndex(x => new { x.Status, x.EffectiveFrom }) - .HasFilter("\"TenantId\" = 0"); - } - - private static void ConfigureTenantAnnouncementRead(EntityTypeBuilder builder) - { - builder.ToTable("tenant_announcement_reads"); - builder.HasKey(x => x.Id); - builder.Property(x => x.TenantId).IsRequired(); - builder.Property(x => x.AnnouncementId).IsRequired(); - builder.Property(x => x.UserId); - builder.Property(x => x.ReadAt).IsRequired(); - ConfigureAuditableEntity(builder); - ConfigureSoftDeleteEntity(builder); - builder.HasIndex(x => new { x.TenantId, x.AnnouncementId, x.UserId }).IsUnique(); - } - - private static void ConfigureMerchantDocument(EntityTypeBuilder builder) - { - builder.ToTable("merchant_documents"); - builder.HasKey(x => x.Id); - builder.Property(x => x.MerchantId).IsRequired(); - builder.Property(x => x.DocumentType).HasConversion(); - builder.Property(x => x.Status).HasConversion(); - builder.Property(x => x.FileUrl).HasMaxLength(512).IsRequired(); - builder.Property(x => x.DocumentNumber).HasMaxLength(64); - builder.HasIndex(x => new { x.TenantId, x.MerchantId, x.DocumentType }); - } - - private static void ConfigureMerchantContract(EntityTypeBuilder builder) - { - builder.ToTable("merchant_contracts"); - builder.HasKey(x => x.Id); - builder.Property(x => x.MerchantId).IsRequired(); - builder.Property(x => x.ContractNumber).HasMaxLength(64).IsRequired(); - builder.Property(x => x.FileUrl).HasMaxLength(512).IsRequired(); - builder.Property(x => x.Status).HasConversion(); - builder.Property(x => x.TerminationReason).HasMaxLength(256); - builder.HasIndex(x => new { x.TenantId, x.MerchantId, x.ContractNumber }).IsUnique(); - } - - private static void ConfigureMerchantStaff(EntityTypeBuilder builder) - { - builder.ToTable("merchant_staff"); - builder.HasKey(x => x.Id); - builder.Property(x => x.MerchantId).IsRequired(); - builder.Property(x => x.Name).HasMaxLength(64).IsRequired(); - builder.Property(x => x.Phone).HasMaxLength(32).IsRequired(); - builder.Property(x => x.Email).HasMaxLength(128); - builder.Property(x => x.RoleType).HasConversion(); - builder.Property(x => x.Status).HasConversion(); - builder.Property(x => x.PermissionsJson).HasColumnType("text"); - builder.HasIndex(x => new { x.TenantId, x.MerchantId, x.Phone }); - } - - private static void ConfigureMerchantCategory(EntityTypeBuilder builder) - { - builder.ToTable("merchant_categories"); - builder.HasKey(x => x.Id); - builder.Property(x => x.Name).HasMaxLength(64).IsRequired(); - builder.Property(x => x.DisplayOrder).HasDefaultValue(0); - builder.Property(x => x.IsActive).IsRequired(); - builder.HasIndex(x => new { x.TenantId, x.Name }).IsUnique(); - } - - private static void ConfigureStoreBusinessHour(EntityTypeBuilder builder) - { - builder.ToTable("store_business_hours"); - builder.HasKey(x => x.Id); - builder.Property(x => x.StoreId).IsRequired(); - builder.Property(x => x.HourType).HasConversion(); - builder.Property(x => x.Notes).HasMaxLength(256); - builder.HasIndex(x => new { x.TenantId, x.StoreId, x.DayOfWeek }); - } - - private static void ConfigureStoreHoliday(EntityTypeBuilder builder) - { - builder.ToTable("store_holidays"); - builder.HasKey(x => x.Id); - builder.Property(x => x.StoreId).IsRequired(); - builder.Property(x => x.Date).IsRequired(); - builder.Property(x => x.EndDate); - builder.Property(x => x.IsAllDay).HasDefaultValue(true); - builder.Property(x => x.StartTime); - builder.Property(x => x.EndTime); - builder.Property(x => x.OverrideType).HasDefaultValue(OverrideType.Closed); - builder.Property(x => x.IsClosed).HasDefaultValue(true); - builder.Property(x => x.Reason).HasMaxLength(200); - builder.HasIndex(x => new { x.TenantId, x.StoreId, x.Date }); - } - - private static void ConfigureStoreDeliveryZone(EntityTypeBuilder builder) - { - builder.ToTable("store_delivery_zones"); - builder.HasKey(x => x.Id); - builder.Property(x => x.StoreId).IsRequired(); - builder.Property(x => x.ZoneName).HasMaxLength(64).IsRequired(); - builder.Property(x => x.PolygonGeoJson).HasColumnType("text").IsRequired(); - builder.Property(x => x.MinimumOrderAmount).HasPrecision(18, 2); - builder.Property(x => x.DeliveryFee).HasPrecision(18, 2); - builder.HasIndex(x => new { x.TenantId, x.StoreId, x.ZoneName }); - } - - private static void ConfigureStoreTableArea(EntityTypeBuilder builder) - { - builder.ToTable("store_table_areas"); - builder.HasKey(x => x.Id); - builder.Property(x => x.StoreId).IsRequired(); - builder.Property(x => x.Name).HasMaxLength(64).IsRequired(); - builder.Property(x => x.Description).HasMaxLength(256); - builder.HasIndex(x => new { x.TenantId, x.StoreId, x.Name }).IsUnique(); - } - - private static void ConfigureStoreTable(EntityTypeBuilder builder) - { - builder.ToTable("store_tables"); - builder.HasKey(x => x.Id); - builder.Property(x => x.StoreId).IsRequired(); - builder.Property(x => x.TableCode).HasMaxLength(32).IsRequired(); - builder.Property(x => x.Tags).HasMaxLength(128); - builder.Property(x => x.QrCodeUrl).HasMaxLength(512); - builder.HasIndex(x => new { x.TenantId, x.StoreId, x.TableCode }).IsUnique(); - } - - private static void ConfigureStoreEmployeeShift(EntityTypeBuilder builder) - { - builder.ToTable("store_employee_shifts"); - builder.HasKey(x => x.Id); - builder.Property(x => x.StoreId).IsRequired(); - builder.Property(x => x.StaffId).IsRequired(); - builder.Property(x => x.RoleType).HasConversion(); - builder.Property(x => x.Notes).HasMaxLength(256); - builder.HasIndex(x => new { x.TenantId, x.StoreId, x.ShiftDate, x.StaffId }).IsUnique(); - } - - private static void ConfigureStorePickupSetting(EntityTypeBuilder builder) - { - builder.ToTable("store_pickup_settings"); - builder.HasKey(x => x.Id); - builder.Property(x => x.StoreId).IsRequired(); - builder.Property(x => x.DefaultCutoffMinutes).HasDefaultValue(30); - builder.Property(x => x.RowVersion) - .IsConcurrencyToken(); - builder.HasIndex(x => new { x.TenantId, x.StoreId }).IsUnique(); - } - - private static void ConfigureStorePickupSlot(EntityTypeBuilder builder) - { - builder.ToTable("store_pickup_slots"); - builder.HasKey(x => x.Id); - builder.Property(x => x.StoreId).IsRequired(); - builder.Property(x => x.Name).HasMaxLength(64).IsRequired(); - builder.Property(x => x.Weekdays).HasMaxLength(32).IsRequired(); - builder.Property(x => x.CutoffMinutes).HasDefaultValue(30); - builder.Property(x => x.RowVersion) - .IsConcurrencyToken(); - builder.HasIndex(x => new { x.TenantId, x.StoreId, x.Name }); - } - - private static void ConfigureProductAttributeGroup(EntityTypeBuilder builder) - { - builder.ToTable("product_attribute_groups"); - builder.HasKey(x => x.Id); - builder.Property(x => x.Name).HasMaxLength(64).IsRequired(); - builder.Property(x => x.SelectionType).HasConversion(); - builder.Property(x => x.StoreId); - builder.HasIndex(x => new { x.TenantId, x.StoreId, x.Name }); - } - - private static void ConfigureProductAttributeOption(EntityTypeBuilder builder) - { - builder.ToTable("product_attribute_options"); - builder.HasKey(x => x.Id); - builder.Property(x => x.AttributeGroupId).IsRequired(); - builder.Property(x => x.Name).HasMaxLength(64).IsRequired(); - builder.Property(x => x.ExtraPrice).HasPrecision(18, 2); - builder.HasIndex(x => new { x.TenantId, x.AttributeGroupId, x.Name }).IsUnique(); - } - - private static void ConfigureProductSku(EntityTypeBuilder builder) - { - builder.ToTable("product_skus"); - builder.HasKey(x => x.Id); - builder.Property(x => x.ProductId).IsRequired(); - builder.Property(x => x.SkuCode).HasMaxLength(32).IsRequired(); - builder.Property(x => x.Barcode).HasMaxLength(64); - builder.Property(x => x.Price).HasPrecision(18, 2); - builder.Property(x => x.OriginalPrice).HasPrecision(18, 2); - builder.Property(x => x.Weight).HasPrecision(10, 3); - builder.Property(x => x.AttributesJson).HasColumnType("text"); - builder.HasIndex(x => new { x.TenantId, x.SkuCode }).IsUnique(); - } - - private static void ConfigureProductAddonGroup(EntityTypeBuilder builder) - { - builder.ToTable("product_addon_groups"); - builder.HasKey(x => x.Id); - builder.Property(x => x.ProductId).IsRequired(); - builder.Property(x => x.Name).HasMaxLength(64).IsRequired(); - builder.Property(x => x.SelectionType).HasConversion(); - builder.HasIndex(x => new { x.TenantId, x.ProductId, x.Name }); - } - - private static void ConfigureProductAddonOption(EntityTypeBuilder builder) - { - builder.ToTable("product_addon_options"); - builder.HasKey(x => x.Id); - builder.Property(x => x.AddonGroupId).IsRequired(); - builder.Property(x => x.Name).HasMaxLength(64).IsRequired(); - builder.Property(x => x.ExtraPrice).HasPrecision(18, 2); - } - - private static void ConfigureProductPricingRule(EntityTypeBuilder builder) - { - builder.ToTable("product_pricing_rules"); - builder.HasKey(x => x.Id); - builder.Property(x => x.ProductId).IsRequired(); - builder.Property(x => x.RuleType).HasConversion(); - builder.Property(x => x.ConditionsJson).HasColumnType("text").IsRequired(); - builder.Property(x => x.Price).HasPrecision(18, 2); - builder.Property(x => x.WeekdaysJson).HasColumnType("text"); - builder.HasIndex(x => new { x.TenantId, x.ProductId, x.RuleType }); - } - - private static void ConfigureProductMediaAsset(EntityTypeBuilder builder) - { - builder.ToTable("product_media_assets"); - builder.HasKey(x => x.Id); - builder.Property(x => x.ProductId).IsRequired(); - builder.Property(x => x.MediaType).HasConversion(); - builder.Property(x => x.Url).HasMaxLength(512).IsRequired(); - builder.Property(x => x.Caption).HasMaxLength(256); - } - - private static void ConfigureInventoryItem(EntityTypeBuilder builder) - { - builder.ToTable("inventory_items"); - builder.HasKey(x => x.Id); - builder.Property(x => x.StoreId).IsRequired(); - builder.Property(x => x.ProductSkuId).IsRequired(); - builder.Property(x => x.BatchNumber).HasMaxLength(64); - builder.Property(x => x.Location).HasMaxLength(64); - builder.Property(x => x.RowVersion) - .IsConcurrencyToken(); - builder.HasIndex(x => new { x.TenantId, x.StoreId, x.ProductSkuId, x.BatchNumber }); - } - - private static void ConfigureInventoryAdjustment(EntityTypeBuilder builder) - { - builder.ToTable("inventory_adjustments"); - builder.HasKey(x => x.Id); - builder.Property(x => x.InventoryItemId).IsRequired(); - builder.Property(x => x.AdjustmentType).HasConversion(); - builder.Property(x => x.Reason).HasMaxLength(256); - builder.HasIndex(x => new { x.TenantId, x.InventoryItemId, x.OccurredAt }); - } - - private static void ConfigureInventoryBatch(EntityTypeBuilder builder) - { - builder.ToTable("inventory_batches"); - builder.HasKey(x => x.Id); - builder.Property(x => x.StoreId).IsRequired(); - builder.Property(x => x.ProductSkuId).IsRequired(); - builder.Property(x => x.BatchNumber).HasMaxLength(64).IsRequired(); - builder.Property(x => x.RowVersion) - .IsConcurrencyToken(); - builder.HasIndex(x => new { x.TenantId, x.StoreId, x.ProductSkuId, x.BatchNumber }).IsUnique(); - } - - private static void ConfigureInventoryLockRecord(EntityTypeBuilder builder) - { - builder.ToTable("inventory_lock_records"); - builder.HasKey(x => x.Id); - builder.Property(x => x.StoreId).IsRequired(); - builder.Property(x => x.ProductSkuId).IsRequired(); - builder.Property(x => x.Quantity).IsRequired(); - builder.Property(x => x.IdempotencyKey).HasMaxLength(128).IsRequired(); - builder.Property(x => x.Status).HasConversion(); - builder.Property(x => x.RowVersion) - .IsConcurrencyToken(); - builder.HasIndex(x => new { x.TenantId, x.IdempotencyKey }).IsUnique(); - builder.HasIndex(x => new { x.TenantId, x.StoreId, x.ProductSkuId, x.Status }); - } - - private static void ConfigureShoppingCart(EntityTypeBuilder builder) - { - builder.ToTable("shopping_carts"); - builder.HasKey(x => x.Id); - builder.Property(x => x.UserId).IsRequired(); - builder.Property(x => x.StoreId).IsRequired(); - builder.Property(x => x.Status).HasConversion(); - builder.Property(x => x.TableContext).HasMaxLength(64); - builder.Property(x => x.DeliveryPreference).HasMaxLength(32); - builder.HasIndex(x => new { x.TenantId, x.UserId, x.StoreId }).IsUnique(); - } - - private static void ConfigureCartItem(EntityTypeBuilder builder) - { - builder.ToTable("cart_items"); - builder.HasKey(x => x.Id); - builder.Property(x => x.ShoppingCartId).IsRequired(); - builder.Property(x => x.ProductId).IsRequired(); - builder.Property(x => x.ProductName).HasMaxLength(128).IsRequired(); - builder.Property(x => x.UnitPrice).HasPrecision(18, 2); - builder.Property(x => x.Remark).HasMaxLength(256); - builder.Property(x => x.Status).HasConversion(); - builder.Property(x => x.AttributesJson).HasColumnType("text"); - builder.HasIndex(x => new { x.TenantId, x.ShoppingCartId }); - } - - private static void ConfigureCartItemAddon(EntityTypeBuilder builder) - { - builder.ToTable("cart_item_addons"); - builder.HasKey(x => x.Id); - builder.Property(x => x.CartItemId).IsRequired(); - builder.Property(x => x.Name).HasMaxLength(64).IsRequired(); - builder.Property(x => x.ExtraPrice).HasPrecision(18, 2); - } - - private static void ConfigureCheckoutSession(EntityTypeBuilder builder) - { - builder.ToTable("checkout_sessions"); - builder.HasKey(x => x.Id); - builder.Property(x => x.UserId).IsRequired(); - builder.Property(x => x.StoreId).IsRequired(); - builder.Property(x => x.SessionToken).HasMaxLength(64).IsRequired(); - builder.Property(x => x.Status).HasConversion(); - builder.Property(x => x.ValidationResultJson).HasColumnType("text").IsRequired(); - builder.HasIndex(x => new { x.TenantId, x.SessionToken }).IsUnique(); - } - - private static void ConfigureOrderStatusHistory(EntityTypeBuilder builder) - { - builder.ToTable("order_status_histories"); - builder.HasKey(x => x.Id); - builder.Property(x => x.OrderId).IsRequired(); - builder.Property(x => x.Status).HasConversion(); - builder.Property(x => x.Notes).HasMaxLength(256); - builder.HasIndex(x => new { x.TenantId, x.OrderId, x.OccurredAt }); - } - - private static void ConfigureRefundRequest(EntityTypeBuilder builder) - { - builder.ToTable("refund_requests"); - builder.HasKey(x => x.Id); - builder.Property(x => x.OrderId).IsRequired(); - builder.Property(x => x.RefundNo).HasMaxLength(32).IsRequired(); - builder.Property(x => x.Amount).HasPrecision(18, 2); - builder.Property(x => x.Reason).HasMaxLength(256).IsRequired(); - builder.Property(x => x.Status).HasConversion(); - builder.Property(x => x.ReviewNotes).HasMaxLength(256); - builder.HasIndex(x => new { x.TenantId, x.RefundNo }).IsUnique(); - } - - private static void ConfigurePaymentRefundRecord(EntityTypeBuilder builder) - { - builder.ToTable("payment_refund_records"); - builder.HasKey(x => x.Id); - builder.Property(x => x.PaymentRecordId).IsRequired(); - builder.Property(x => x.OrderId).IsRequired(); - builder.Property(x => x.Amount).HasPrecision(18, 2); - builder.Property(x => x.ChannelRefundId).HasMaxLength(64); - builder.Property(x => x.Status).HasConversion(); - builder.Property(x => x.Payload).HasColumnType("text"); - builder.HasIndex(x => new { x.TenantId, x.PaymentRecordId }); - } - - private static void ConfigureDeliveryEvent(EntityTypeBuilder builder) - { - builder.ToTable("delivery_events"); - builder.HasKey(x => x.Id); - builder.Property(x => x.DeliveryOrderId).IsRequired(); - builder.Property(x => x.EventType).HasConversion(); - builder.Property(x => x.Message).HasMaxLength(256); - builder.Property(x => x.Payload).HasColumnType("text"); - builder.HasIndex(x => new { x.TenantId, x.DeliveryOrderId, x.EventType }); - } - - private static void ConfigureGroupOrder(EntityTypeBuilder builder) - { - builder.ToTable("group_orders"); - builder.HasKey(x => x.Id); - builder.Property(x => x.GroupOrderNo).HasMaxLength(32).IsRequired(); - builder.Property(x => x.GroupPrice).HasPrecision(18, 2); - builder.Property(x => x.Status).HasConversion(); - builder.HasIndex(x => new { x.TenantId, x.GroupOrderNo }).IsUnique(); - } - - private static void ConfigureGroupParticipant(EntityTypeBuilder builder) - { - builder.ToTable("group_participants"); - builder.HasKey(x => x.Id); - builder.Property(x => x.GroupOrderId).IsRequired(); - builder.Property(x => x.OrderId).IsRequired(); - builder.Property(x => x.Status).HasConversion(); - builder.HasIndex(x => new { x.TenantId, x.GroupOrderId, x.UserId }).IsUnique(); - } - - private static void ConfigureCouponTemplate(EntityTypeBuilder builder) - { - builder.ToTable("coupon_templates"); - builder.HasKey(x => x.Id); - builder.Property(x => x.Name).HasMaxLength(128).IsRequired(); - builder.Property(x => x.CouponType).HasConversion(); - builder.Property(x => x.Description).HasMaxLength(512); - builder.Property(x => x.TotalQuantity); - builder.Property(x => x.StoreScopeJson).HasColumnType("text"); - builder.Property(x => x.ProductScopeJson).HasColumnType("text"); - builder.Property(x => x.ChannelsJson).HasColumnType("text"); - builder.Property(x => x.Status).HasConversion(); - } - - private static void ConfigureCoupon(EntityTypeBuilder builder) - { - builder.ToTable("coupons"); - builder.HasKey(x => x.Id); - builder.Property(x => x.CouponTemplateId).IsRequired(); - builder.Property(x => x.Code).HasMaxLength(32).IsRequired(); - builder.Property(x => x.Status).HasConversion(); - builder.HasIndex(x => new { x.TenantId, x.Code }).IsUnique(); - } - - private static void ConfigurePromotionCampaign(EntityTypeBuilder builder) - { - builder.ToTable("promotion_campaigns"); - builder.HasKey(x => x.Id); - builder.Property(x => x.Name).HasMaxLength(128).IsRequired(); - builder.Property(x => x.PromotionType).HasConversion(); - builder.Property(x => x.Status).HasConversion(); - builder.Property(x => x.RulesJson).HasColumnType("text").IsRequired(); - builder.Property(x => x.AudienceDescription).HasMaxLength(512); - builder.Property(x => x.BannerUrl).HasMaxLength(512); - } - - private static void ConfigureMemberProfile(EntityTypeBuilder builder) - { - builder.ToTable("member_profiles"); - builder.HasKey(x => x.Id); - builder.Property(x => x.Mobile).HasMaxLength(32).IsRequired(); - builder.Property(x => x.Nickname).HasMaxLength(64); - builder.Property(x => x.AvatarUrl).HasMaxLength(256); - builder.Property(x => x.Status).HasConversion(); - builder.HasIndex(x => new { x.TenantId, x.Mobile }).IsUnique(); - } - - private static void ConfigureMemberTier(EntityTypeBuilder builder) - { - builder.ToTable("member_tiers"); - builder.HasKey(x => x.Id); - builder.Property(x => x.Name).HasMaxLength(64).IsRequired(); - builder.Property(x => x.BenefitsJson).HasColumnType("text"); - builder.HasIndex(x => new { x.TenantId, x.Name }).IsUnique(); - } - - private static void ConfigureMemberPointLedger(EntityTypeBuilder builder) - { - builder.ToTable("member_point_ledgers"); - builder.HasKey(x => x.Id); - builder.Property(x => x.MemberId).IsRequired(); - builder.Property(x => x.Reason).HasConversion(); - builder.HasIndex(x => new { x.TenantId, x.MemberId, x.OccurredAt }); - } - - private static void ConfigureChatSession(EntityTypeBuilder builder) - { - builder.ToTable("chat_sessions"); - builder.HasKey(x => x.Id); - builder.Property(x => x.SessionCode).HasMaxLength(64).IsRequired(); - builder.Property(x => x.Status).HasConversion(); - builder.HasIndex(x => new { x.TenantId, x.SessionCode }).IsUnique(); - } - - private static void ConfigureChatMessage(EntityTypeBuilder builder) - { - builder.ToTable("chat_messages"); - builder.HasKey(x => x.Id); - builder.Property(x => x.ChatSessionId).IsRequired(); - builder.Property(x => x.SenderType).HasConversion(); - builder.Property(x => x.ContentType).HasMaxLength(64).IsRequired(); - builder.Property(x => x.Content).HasMaxLength(1024).IsRequired(); - builder.HasIndex(x => new { x.TenantId, x.ChatSessionId, x.CreatedAt }); - } - - private static void ConfigureSupportTicket(EntityTypeBuilder builder) - { - builder.ToTable("support_tickets"); - builder.HasKey(x => x.Id); - builder.Property(x => x.TicketNo).HasMaxLength(32).IsRequired(); - builder.Property(x => x.Subject).HasMaxLength(128).IsRequired(); - builder.Property(x => x.Description).HasColumnType("text").IsRequired(); - builder.Property(x => x.Priority).HasConversion(); - builder.Property(x => x.Status).HasConversion(); - builder.HasIndex(x => new { x.TenantId, x.TicketNo }).IsUnique(); - } - - private static void ConfigureTicketComment(EntityTypeBuilder builder) - { - builder.ToTable("ticket_comments"); - builder.HasKey(x => x.Id); - builder.Property(x => x.SupportTicketId).IsRequired(); - builder.Property(x => x.Content).HasMaxLength(1024).IsRequired(); - builder.Property(x => x.AttachmentsJson).HasColumnType("text"); - builder.HasIndex(x => new { x.TenantId, x.SupportTicketId }); - } - - private static void ConfigureAffiliatePartner(EntityTypeBuilder builder) - { - builder.ToTable("affiliate_partners"); - builder.HasKey(x => x.Id); - builder.Property(x => x.DisplayName).HasMaxLength(64).IsRequired(); - builder.Property(x => x.Phone).HasMaxLength(32); - builder.Property(x => x.ChannelType).HasConversion(); - builder.Property(x => x.Status).HasConversion(); - builder.Property(x => x.Remarks).HasMaxLength(256); - builder.HasIndex(x => new { x.TenantId, x.DisplayName }); - } - - private static void ConfigureAffiliateOrder(EntityTypeBuilder builder) - { - builder.ToTable("affiliate_orders"); - builder.HasKey(x => x.Id); - builder.Property(x => x.AffiliatePartnerId).IsRequired(); - builder.Property(x => x.OrderId).IsRequired(); - builder.Property(x => x.OrderAmount).HasPrecision(18, 2); - builder.Property(x => x.EstimatedCommission).HasPrecision(18, 2); - builder.Property(x => x.Status).HasConversion(); - builder.HasIndex(x => new { x.TenantId, x.AffiliatePartnerId, x.OrderId }).IsUnique(); - } - - private static void ConfigureAffiliatePayout(EntityTypeBuilder builder) - { - builder.ToTable("affiliate_payouts"); - builder.HasKey(x => x.Id); - builder.Property(x => x.AffiliatePartnerId).IsRequired(); - builder.Property(x => x.Period).HasMaxLength(32).IsRequired(); - builder.Property(x => x.Amount).HasPrecision(18, 2); - builder.Property(x => x.Status).HasConversion(); - builder.Property(x => x.Remarks).HasMaxLength(256); - builder.HasIndex(x => new { x.TenantId, x.AffiliatePartnerId, x.Period }).IsUnique(); - } - - private static void ConfigureCheckInCampaign(EntityTypeBuilder builder) - { - builder.ToTable("checkin_campaigns"); - builder.HasKey(x => x.Id); - builder.Property(x => x.Name).HasMaxLength(128).IsRequired(); - builder.Property(x => x.Description).HasMaxLength(512); - builder.Property(x => x.RewardsJson).HasColumnType("text").IsRequired(); - builder.Property(x => x.Status).HasConversion(); - builder.HasIndex(x => new { x.TenantId, x.Name }); - } - - private static void ConfigureCheckInRecord(EntityTypeBuilder builder) - { - builder.ToTable("checkin_records"); - builder.HasKey(x => x.Id); - builder.Property(x => x.CheckInCampaignId).IsRequired(); - builder.Property(x => x.UserId).IsRequired(); - builder.Property(x => x.RewardJson).HasColumnType("text").IsRequired(); - builder.HasIndex(x => new { x.TenantId, x.CheckInCampaignId, x.UserId, x.CheckInDate }).IsUnique(); - } - - private static void ConfigureCommunityPost(EntityTypeBuilder builder) - { - builder.ToTable("community_posts"); - builder.HasKey(x => x.Id); - builder.Property(x => x.AuthorUserId).IsRequired(); - builder.Property(x => x.Title).HasMaxLength(128); - builder.Property(x => x.Content).HasColumnType("text").IsRequired(); - builder.Property(x => x.MediaJson).HasColumnType("text"); - builder.Property(x => x.Status).HasConversion(); - builder.HasIndex(x => new { x.TenantId, x.AuthorUserId, x.CreatedAt }); - } - - private static void ConfigureCommunityComment(EntityTypeBuilder builder) - { - builder.ToTable("community_comments"); - builder.HasKey(x => x.Id); - builder.Property(x => x.PostId).IsRequired(); - builder.Property(x => x.Content).HasMaxLength(512).IsRequired(); - builder.HasIndex(x => new { x.TenantId, x.PostId, x.CreatedAt }); - } - - private static void ConfigureCommunityReaction(EntityTypeBuilder builder) - { - builder.ToTable("community_reactions"); - builder.HasKey(x => x.Id); - builder.Property(x => x.PostId).IsRequired(); - builder.Property(x => x.ReactionType).HasConversion(); - builder.HasIndex(x => new { x.TenantId, x.PostId, x.UserId }).IsUnique(); - } - - private static void ConfigureMapLocation(EntityTypeBuilder builder) - { - builder.ToTable("map_locations"); - builder.HasKey(x => x.Id); - builder.Property(x => x.Name).HasMaxLength(128).IsRequired(); - builder.Property(x => x.Address).HasMaxLength(256).IsRequired(); - builder.Property(x => x.Landmark).HasMaxLength(128); - builder.HasIndex(x => new { x.TenantId, x.StoreId }); - } - - private static void ConfigureNavigationRequest(EntityTypeBuilder builder) - { - builder.ToTable("navigation_requests"); - builder.HasKey(x => x.Id); - builder.Property(x => x.UserId).IsRequired(); - builder.Property(x => x.StoreId).IsRequired(); - builder.Property(x => x.Channel).HasConversion(); - builder.Property(x => x.TargetApp).HasConversion(); - builder.HasIndex(x => new { x.TenantId, x.UserId, x.StoreId, x.RequestedAt }); - } - - private static void ConfigureMetricDefinition(EntityTypeBuilder builder) - { - builder.ToTable("metric_definitions"); - builder.HasKey(x => x.Id); - builder.Property(x => x.Code).HasMaxLength(64).IsRequired(); - builder.Property(x => x.Name).HasMaxLength(128).IsRequired(); - builder.Property(x => x.Description).HasMaxLength(512); - builder.Property(x => x.DimensionsJson).HasColumnType("text"); - builder.Property(x => x.DefaultAggregation).HasMaxLength(32).IsRequired(); - builder.HasIndex(x => new { x.TenantId, x.Code }).IsUnique(); - } - - private static void ConfigureMetricSnapshot(EntityTypeBuilder builder) - { - builder.ToTable("metric_snapshots"); - builder.HasKey(x => x.Id); - builder.Property(x => x.MetricDefinitionId).IsRequired(); - builder.Property(x => x.DimensionKey).HasMaxLength(256).IsRequired(); - builder.Property(x => x.Value).HasPrecision(18, 4); - builder.HasIndex(x => new { x.TenantId, x.MetricDefinitionId, x.DimensionKey, x.WindowStart, x.WindowEnd }).IsUnique(); - } - - private static void ConfigureMetricAlertRule(EntityTypeBuilder builder) - { - builder.ToTable("metric_alert_rules"); - builder.HasKey(x => x.Id); - builder.Property(x => x.MetricDefinitionId).IsRequired(); - builder.Property(x => x.ConditionJson).HasColumnType("text").IsRequired(); - builder.Property(x => x.Severity).HasConversion(); - builder.Property(x => x.NotificationChannels).HasMaxLength(256); - builder.HasIndex(x => new { x.TenantId, x.MetricDefinitionId, x.Severity }); - } - - private static void ConfigureQuotaPackage(EntityTypeBuilder builder) - { - builder.ToTable("quota_packages"); - builder.HasKey(x => x.Id); - builder.Property(x => x.Name).HasMaxLength(128).IsRequired(); - builder.Property(x => x.QuotaType).HasConversion().IsRequired(); - builder.Property(x => x.QuotaValue).HasPrecision(18, 2).IsRequired(); - builder.Property(x => x.Price).HasPrecision(18, 2).IsRequired(); - builder.Property(x => x.IsActive).IsRequired(); - builder.Property(x => x.SortOrder).HasDefaultValue(0); - builder.Property(x => x.Description).HasMaxLength(512); - builder.HasIndex(x => new { x.QuotaType, x.IsActive, x.SortOrder }); - } - - private static void ConfigureTenantQuotaPackagePurchase(EntityTypeBuilder builder) - { - builder.ToTable("tenant_quota_package_purchases"); - builder.HasKey(x => x.Id); - builder.Property(x => x.TenantId).IsRequired(); - builder.Property(x => x.QuotaPackageId).IsRequired(); - builder.Property(x => x.QuotaValue).HasPrecision(18, 2).IsRequired(); - builder.Property(x => x.Price).HasPrecision(18, 2).IsRequired(); - builder.Property(x => x.PurchasedAt).IsRequired(); - builder.Property(x => x.Notes).HasMaxLength(512); - builder.HasIndex(x => new { x.TenantId, x.QuotaPackageId, x.PurchasedAt }); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/TakeoutAppDesignTimeDbContextFactory.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/TakeoutAppDesignTimeDbContextFactory.cs deleted file mode 100644 index 9146c16..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/TakeoutAppDesignTimeDbContextFactory.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Infrastructure.Common.Persistence.DesignTime; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Infrastructure.App.Persistence; - -/// -/// 设计时工厂,供 EF CLI 使用。 -/// -internal sealed class TakeoutAppDesignTimeDbContextFactory - : DesignTimeDbContextFactoryBase -{ - /// - /// 初始化业务库设计时上下文工厂。 - /// - public TakeoutAppDesignTimeDbContextFactory() - : base(DatabaseConstants.AppDataSource, "TAKEOUTSAAS_APP_CONNECTION") - { - } - // 创建设计时上下文 - /// - /// 创建设计时的业务库 DbContext。 - /// - /// 上下文选项。 - /// 租户提供器。 - /// 当前用户访问器。 - /// 业务库上下文实例。 - protected override TakeoutAppDbContext CreateContext( - DbContextOptions options, - ITenantProvider tenantProvider, - ICurrentUserAccessor currentUserAccessor) - => new(options, tenantProvider, currentUserAccessor); -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfDeliveryRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfDeliveryRepository.cs deleted file mode 100644 index 3bc734d..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfDeliveryRepository.cs +++ /dev/null @@ -1,117 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Deliveries.Entities; -using TakeoutSaaS.Domain.Deliveries.Enums; -using TakeoutSaaS.Domain.Deliveries.Repositories; -using TakeoutSaaS.Infrastructure.App.Persistence; - -namespace TakeoutSaaS.Infrastructure.App.Repositories; - -/// -/// 配送聚合的 EF Core 仓储实现。 -/// -/// -/// 初始化仓储。 -/// -public sealed class EfDeliveryRepository(TakeoutAppDbContext context) : IDeliveryRepository -{ - /// - public Task FindByIdAsync(long deliveryOrderId, long tenantId, CancellationToken cancellationToken = default) - { - return context.DeliveryOrders - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.Id == deliveryOrderId) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public Task FindByOrderIdAsync(long orderId, long tenantId, CancellationToken cancellationToken = default) - { - return context.DeliveryOrders - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.OrderId == orderId) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public async Task> GetEventsAsync(long deliveryOrderId, long tenantId, CancellationToken cancellationToken = default) - { - var events = await context.DeliveryEvents - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.DeliveryOrderId == deliveryOrderId) - .OrderBy(x => x.CreatedAt) - .ToListAsync(cancellationToken); - - return events; - } - - /// - public Task AddDeliveryOrderAsync(DeliveryOrder deliveryOrder, CancellationToken cancellationToken = default) - { - return context.DeliveryOrders.AddAsync(deliveryOrder, cancellationToken).AsTask(); - } - - /// - public Task AddEventAsync(DeliveryEvent deliveryEvent, CancellationToken cancellationToken = default) - { - return context.DeliveryEvents.AddAsync(deliveryEvent, cancellationToken).AsTask(); - } - - /// - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - { - return context.SaveChangesAsync(cancellationToken); - } - - /// - public async Task> SearchAsync(long tenantId, DeliveryStatus? status, long? orderId, CancellationToken cancellationToken = default) - { - var query = context.DeliveryOrders - .AsNoTracking() - .Where(x => x.TenantId == tenantId); - - if (status.HasValue) - { - query = query.Where(x => x.Status == status.Value); - } - - if (orderId.HasValue) - { - query = query.Where(x => x.OrderId == orderId.Value); - } - - return await query - .OrderByDescending(x => x.CreatedAt) - .ToListAsync(cancellationToken); - } - - /// - public Task UpdateDeliveryOrderAsync(DeliveryOrder deliveryOrder, CancellationToken cancellationToken = default) - { - context.DeliveryOrders.Update(deliveryOrder); - return Task.CompletedTask; - } - - /// - public async Task DeleteDeliveryOrderAsync(long deliveryOrderId, long tenantId, CancellationToken cancellationToken = default) - { - var events = await context.DeliveryEvents - .Where(x => x.TenantId == tenantId && x.DeliveryOrderId == deliveryOrderId) - .ToListAsync(cancellationToken); - - if (events.Count > 0) - { - context.DeliveryEvents.RemoveRange(events); - } - - var existing = await context.DeliveryOrders - .Where(x => x.TenantId == tenantId && x.Id == deliveryOrderId) - .FirstOrDefaultAsync(cancellationToken); - - if (existing == null) - { - return; - } - - context.DeliveryOrders.Remove(existing); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfInventoryRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfInventoryRepository.cs deleted file mode 100644 index 0cc6526..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfInventoryRepository.cs +++ /dev/null @@ -1,145 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Inventory.Entities; -using TakeoutSaaS.Domain.Inventory.Enums; -using TakeoutSaaS.Domain.Inventory.Repositories; -using TakeoutSaaS.Infrastructure.App.Persistence; - -namespace TakeoutSaaS.Infrastructure.App.Repositories; - -/// -/// 库存仓储 EF 实现。 -/// -/// -/// 提供库存与批次的读写能力。 -/// -public sealed class EfInventoryRepository(TakeoutAppDbContext context) : IInventoryRepository -{ - /// - public Task FindByIdAsync(long inventoryItemId, long tenantId, CancellationToken cancellationToken = default) - { - return context.InventoryItems - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.Id == inventoryItemId) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public Task FindBySkuAsync(long tenantId, long storeId, long productSkuId, CancellationToken cancellationToken = default) - { - return context.InventoryItems - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.StoreId == storeId && x.ProductSkuId == productSkuId) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public Task GetForUpdateAsync(long tenantId, long storeId, long productSkuId, CancellationToken cancellationToken = default) - { - return context.InventoryItems - .Where(x => x.TenantId == tenantId && x.StoreId == storeId && x.ProductSkuId == productSkuId) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public Task AddItemAsync(InventoryItem item, CancellationToken cancellationToken = default) - { - return context.InventoryItems.AddAsync(item, cancellationToken).AsTask(); - } - - /// - public Task UpdateItemAsync(InventoryItem item, CancellationToken cancellationToken = default) - { - context.InventoryItems.Update(item); - return Task.CompletedTask; - } - - /// - public Task AddAdjustmentAsync(InventoryAdjustment adjustment, CancellationToken cancellationToken = default) - { - return context.InventoryAdjustments.AddAsync(adjustment, cancellationToken).AsTask(); - } - - /// - public Task AddLockAsync(InventoryLockRecord lockRecord, CancellationToken cancellationToken = default) - { - return context.InventoryLockRecords.AddAsync(lockRecord, cancellationToken).AsTask(); - } - - /// - public Task FindLockByKeyAsync(long tenantId, string idempotencyKey, CancellationToken cancellationToken = default) - { - return context.InventoryLockRecords - .Where(x => x.TenantId == tenantId && x.IdempotencyKey == idempotencyKey) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public Task MarkLockStatusAsync(InventoryLockRecord lockRecord, InventoryLockStatus status, CancellationToken cancellationToken = default) - { - lockRecord.Status = status; - context.InventoryLockRecords.Update(lockRecord); - return Task.CompletedTask; - } - - /// - public async Task> FindExpiredLocksAsync(long tenantId, DateTime utcNow, CancellationToken cancellationToken = default) - { - var locks = await context.InventoryLockRecords - .Where(x => x.TenantId == tenantId && x.Status == InventoryLockStatus.Locked && x.ExpiresAt != null && x.ExpiresAt <= utcNow) - .ToListAsync(cancellationToken); - return locks; - } - - /// - public async Task> GetBatchesForConsumeAsync(long tenantId, long storeId, long productSkuId, InventoryBatchConsumeStrategy strategy, CancellationToken cancellationToken = default) - { - var query = context.InventoryBatches - .Where(x => x.TenantId == tenantId && x.StoreId == storeId && x.ProductSkuId == productSkuId); - - query = strategy == InventoryBatchConsumeStrategy.Fefo - ? query.OrderBy(x => x.ExpireDate ?? DateTime.MaxValue).ThenBy(x => x.BatchNumber) - : query.OrderBy(x => x.BatchNumber); - - return await query.ToListAsync(cancellationToken); - } - - /// - public async Task> GetBatchesAsync(long tenantId, long storeId, long productSkuId, CancellationToken cancellationToken = default) - { - var batches = await context.InventoryBatches - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.StoreId == storeId && x.ProductSkuId == productSkuId) - .OrderBy(x => x.ExpireDate ?? DateTime.MaxValue) - .ThenBy(x => x.BatchNumber) - .ToListAsync(cancellationToken); - - return batches; - } - - /// - public Task GetBatchForUpdateAsync(long tenantId, long storeId, long productSkuId, string batchNumber, CancellationToken cancellationToken = default) - { - return context.InventoryBatches - .Where(x => x.TenantId == tenantId && x.StoreId == storeId && x.ProductSkuId == productSkuId && x.BatchNumber == batchNumber) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public Task AddBatchAsync(InventoryBatch batch, CancellationToken cancellationToken = default) - { - return context.InventoryBatches.AddAsync(batch, cancellationToken).AsTask(); - } - - /// - public Task UpdateBatchAsync(InventoryBatch batch, CancellationToken cancellationToken = default) - { - context.InventoryBatches.Update(batch); - return Task.CompletedTask; - } - - /// - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - { - return context.SaveChangesAsync(cancellationToken); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfMerchantCategoryRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfMerchantCategoryRepository.cs deleted file mode 100644 index f832908..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfMerchantCategoryRepository.cs +++ /dev/null @@ -1,66 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Merchants.Entities; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Infrastructure.App.Persistence; - -namespace TakeoutSaaS.Infrastructure.App.Repositories; - -/// -/// 商户类目的 EF Core 仓储实现。 -/// -public sealed class EfMerchantCategoryRepository(TakeoutAppDbContext context) - : IMerchantCategoryRepository -{ - /// - public async Task> ListAsync(long tenantId, CancellationToken cancellationToken = default) - { - var items = await context.MerchantCategories - .AsNoTracking() - .Where(x => x.TenantId == tenantId) - .OrderBy(x => x.DisplayOrder) - .ThenBy(x => x.CreatedAt) - .ToListAsync(cancellationToken); - - return items; - } - - /// - public Task ExistsAsync(string name, long tenantId, CancellationToken cancellationToken = default) - { - return context.MerchantCategories.AnyAsync( - x => x.TenantId == tenantId && x.Name == name, cancellationToken); - } - - /// - public Task FindByIdAsync(long id, long tenantId, CancellationToken cancellationToken = default) - { - return context.MerchantCategories - .FirstOrDefaultAsync(x => x.TenantId == tenantId && x.Id == id, cancellationToken); - } - - /// - public Task AddAsync(MerchantCategory category, CancellationToken cancellationToken = default) - { - return context.MerchantCategories.AddAsync(category, cancellationToken).AsTask(); - } - - /// - public Task RemoveAsync(MerchantCategory category, CancellationToken cancellationToken = default) - { - context.MerchantCategories.Remove(category); - return Task.CompletedTask; - } - - /// - public Task UpdateRangeAsync(IEnumerable categories, CancellationToken cancellationToken = default) - { - context.MerchantCategories.UpdateRange(categories); - return Task.CompletedTask; - } - - /// - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - { - return context.SaveChangesAsync(cancellationToken); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfMerchantRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfMerchantRepository.cs deleted file mode 100644 index 03e14da..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfMerchantRepository.cs +++ /dev/null @@ -1,288 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Common.Enums; -using TakeoutSaaS.Domain.Merchants.Entities; -using TakeoutSaaS.Domain.Merchants.Enums; -using TakeoutSaaS.Domain.Merchants.Repositories; -using TakeoutSaaS.Infrastructure.App.Persistence; -using TakeoutSaaS.Infrastructure.Logs.Persistence; - -namespace TakeoutSaaS.Infrastructure.App.Repositories; - -/// -/// 商户聚合的 EF Core 仓储实现。 -/// -/// -/// 初始化仓储。 -/// -public sealed class EfMerchantRepository(TakeoutAppDbContext context, TakeoutLogsDbContext logsContext) : IMerchantRepository -{ - /// - public Task FindByIdAsync(long merchantId, long tenantId, CancellationToken cancellationToken = default) - { - return context.Merchants - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.Id == merchantId) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public Task GetForUpdateAsync(long merchantId, long tenantId, CancellationToken cancellationToken = default) - { - return context.Merchants - .Where(x => x.TenantId == tenantId && x.Id == merchantId) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public async Task> SearchAsync(long tenantId, MerchantStatus? status, CancellationToken cancellationToken = default) - { - var query = context.Merchants - .AsNoTracking() - .Where(x => x.TenantId == tenantId); - - if (status.HasValue) - { - query = query.Where(x => x.Status == status.Value); - } - - return await query - .OrderByDescending(x => x.CreatedAt) - .ToListAsync(cancellationToken); - } - - /// - public async Task> GetStaffAsync(long merchantId, long tenantId, CancellationToken cancellationToken = default) - { - var staffs = await context.MerchantStaff - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.MerchantId == merchantId) - .OrderBy(x => x.Name) - .ToListAsync(cancellationToken); - - return staffs; - } - - /// - public async Task> GetStaffByStoreAsync(long storeId, long tenantId, CancellationToken cancellationToken = default) - { - var staffs = await context.MerchantStaff - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.StoreId == storeId) - .OrderBy(x => x.Name) - .ToListAsync(cancellationToken); - - return staffs; - } - - /// - public Task FindStaffByIdAsync(long staffId, long tenantId, CancellationToken cancellationToken = default) - { - return context.MerchantStaff - .Where(x => x.TenantId == tenantId && x.Id == staffId) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public async Task> GetContractsAsync(long merchantId, long tenantId, CancellationToken cancellationToken = default) - { - var contracts = await context.MerchantContracts - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.MerchantId == merchantId) - .OrderByDescending(x => x.CreatedAt) - .ToListAsync(cancellationToken); - - return contracts; - } - - /// - public Task FindContractByIdAsync(long merchantId, long tenantId, long contractId, CancellationToken cancellationToken = default) - { - return context.MerchantContracts - .Where(x => x.TenantId == tenantId && x.MerchantId == merchantId && x.Id == contractId) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public async Task> GetDocumentsAsync(long merchantId, long tenantId, CancellationToken cancellationToken = default) - { - var documents = await context.MerchantDocuments - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.MerchantId == merchantId) - .OrderBy(x => x.CreatedAt) - .ToListAsync(cancellationToken); - - return documents; - } - - /// - public Task FindDocumentByIdAsync(long merchantId, long tenantId, long documentId, CancellationToken cancellationToken = default) - { - return context.MerchantDocuments - .Where(x => x.TenantId == tenantId && x.MerchantId == merchantId && x.Id == documentId) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public Task AddMerchantAsync(Merchant merchant, CancellationToken cancellationToken = default) - { - return context.Merchants.AddAsync(merchant, cancellationToken).AsTask(); - } - - /// - public Task AddStaffAsync(MerchantStaff staff, CancellationToken cancellationToken = default) - { - return context.MerchantStaff.AddAsync(staff, cancellationToken).AsTask(); - } - - /// - public Task AddContractAsync(MerchantContract contract, CancellationToken cancellationToken = default) - { - return context.MerchantContracts.AddAsync(contract, cancellationToken).AsTask(); - } - - /// - public Task UpdateContractAsync(MerchantContract contract, CancellationToken cancellationToken = default) - { - context.MerchantContracts.Update(contract); - return Task.CompletedTask; - } - - /// - public Task AddDocumentAsync(MerchantDocument document, CancellationToken cancellationToken = default) - { - return context.MerchantDocuments.AddAsync(document, cancellationToken).AsTask(); - } - - /// - public Task UpdateDocumentAsync(MerchantDocument document, CancellationToken cancellationToken = default) - { - context.MerchantDocuments.Update(document); - return Task.CompletedTask; - } - - /// - public async Task SaveChangesAsync(CancellationToken cancellationToken = default) - { - // 1. 保存业务库变更 - await context.SaveChangesAsync(cancellationToken); - - // 2. 保存日志库变更 - await logsContext.SaveChangesAsync(cancellationToken); - } - - /// - public Task UpdateMerchantAsync(Merchant merchant, CancellationToken cancellationToken = default) - { - context.Merchants.Update(merchant); - return Task.CompletedTask; - } - - /// - public async Task DeleteMerchantAsync(long merchantId, long tenantId, CancellationToken cancellationToken = default) - { - var existing = await context.Merchants - .Where(x => x.TenantId == tenantId && x.Id == merchantId) - .FirstOrDefaultAsync(cancellationToken); - - if (existing == null) - { - return; - } - - context.Merchants.Remove(existing); - } - - /// - public async Task DeleteStaffAsync(long staffId, long tenantId, CancellationToken cancellationToken = default) - { - var existing = await context.MerchantStaff - .Where(x => x.TenantId == tenantId && x.Id == staffId) - .FirstOrDefaultAsync(cancellationToken); - - if (existing == null) - { - return; - } - - context.MerchantStaff.Remove(existing); - } - - /// - public Task AddAuditLogAsync(MerchantAuditLog log, CancellationToken cancellationToken = default) - { - return logsContext.MerchantAuditLogs.AddAsync(log, cancellationToken).AsTask(); - } - - /// - public async Task> GetAuditLogsAsync(long merchantId, long tenantId, CancellationToken cancellationToken = default) - { - return await logsContext.MerchantAuditLogs - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.MerchantId == merchantId) - .OrderByDescending(x => x.CreatedAt) - .ToListAsync(cancellationToken); - } - - /// - public async Task> SearchAsync( - long tenantId, - MerchantStatus? status, - OperatingMode? operatingMode, - string? keyword, - CancellationToken cancellationToken = default) - { - var query = context.Merchants - .AsNoTracking() - .Where(x => x.TenantId == tenantId) - .AsQueryable(); - - if (status.HasValue) - { - query = query.Where(x => x.Status == status.Value); - } - - if (operatingMode.HasValue) - { - query = query.Where(x => x.OperatingMode == operatingMode.Value); - } - - if (!string.IsNullOrWhiteSpace(keyword)) - { - var normalized = keyword.Trim(); - query = query.Where(x => - EF.Functions.ILike(x.BrandName, $"%{normalized}%") || - EF.Functions.ILike(x.BusinessLicenseNumber ?? string.Empty, $"%{normalized}%")); - } - - return await query - .OrderByDescending(x => x.CreatedAt) - .ToListAsync(cancellationToken); - } - - /// - public Task AddChangeLogAsync(MerchantChangeLog log, CancellationToken cancellationToken = default) - { - return logsContext.MerchantChangeLogs.AddAsync(log, cancellationToken).AsTask(); - } - - /// - public async Task> GetChangeLogsAsync( - long merchantId, - long tenantId, - string? fieldName = null, - CancellationToken cancellationToken = default) - { - var query = logsContext.MerchantChangeLogs - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.MerchantId == merchantId); - - if (!string.IsNullOrWhiteSpace(fieldName)) - { - query = query.Where(x => x.FieldName == fieldName); - } - - return await query - .OrderByDescending(x => x.CreatedAt) - .ToListAsync(cancellationToken); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfOrderRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfOrderRepository.cs deleted file mode 100644 index ba663d4..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfOrderRepository.cs +++ /dev/null @@ -1,170 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Orders.Entities; -using TakeoutSaaS.Domain.Orders.Enums; -using TakeoutSaaS.Domain.Orders.Repositories; -using TakeoutSaaS.Domain.Payments.Enums; -using TakeoutSaaS.Infrastructure.App.Persistence; - -namespace TakeoutSaaS.Infrastructure.App.Repositories; - -/// -/// 订单聚合的 EF Core 仓储实现。 -/// -/// -/// 初始化仓储。 -/// -public sealed class EfOrderRepository(TakeoutAppDbContext context) : IOrderRepository -{ - /// - public Task FindByIdAsync(long orderId, long tenantId, CancellationToken cancellationToken = default) - { - return context.Orders - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.Id == orderId) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public Task FindByOrderNoAsync(string orderNo, long tenantId, CancellationToken cancellationToken = default) - { - return context.Orders - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.OrderNo == orderNo) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public async Task> SearchAsync(long tenantId, OrderStatus? status, PaymentStatus? paymentStatus, CancellationToken cancellationToken = default) - { - var query = context.Orders - .AsNoTracking() - .Where(x => x.TenantId == tenantId); - - if (status.HasValue) - { - query = query.Where(x => x.Status == status.Value); - } - - if (paymentStatus.HasValue) - { - query = query.Where(x => x.PaymentStatus == paymentStatus.Value); - } - - var orders = await query - .OrderByDescending(x => x.CreatedAt) - .ToListAsync(cancellationToken); - - return orders; - } - - /// - public async Task> GetItemsAsync(long orderId, long tenantId, CancellationToken cancellationToken = default) - { - var items = await context.OrderItems - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.OrderId == orderId) - .OrderBy(x => x.Id) - .ToListAsync(cancellationToken); - - return items; - } - - /// - public async Task> GetStatusHistoryAsync(long orderId, long tenantId, CancellationToken cancellationToken = default) - { - var histories = await context.OrderStatusHistories - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.OrderId == orderId) - .OrderBy(x => x.CreatedAt) - .ToListAsync(cancellationToken); - - return histories; - } - - /// - public async Task> GetRefundsAsync(long orderId, long tenantId, CancellationToken cancellationToken = default) - { - var refunds = await context.RefundRequests - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.OrderId == orderId) - .OrderByDescending(x => x.CreatedAt) - .ToListAsync(cancellationToken); - - return refunds; - } - - /// - public Task AddOrderAsync(Order order, CancellationToken cancellationToken = default) - { - return context.Orders.AddAsync(order, cancellationToken).AsTask(); - } - - /// - public Task AddItemsAsync(IEnumerable items, CancellationToken cancellationToken = default) - { - return context.OrderItems.AddRangeAsync(items, cancellationToken); - } - - /// - public Task AddStatusHistoryAsync(OrderStatusHistory history, CancellationToken cancellationToken = default) - { - return context.OrderStatusHistories.AddAsync(history, cancellationToken).AsTask(); - } - - /// - public Task AddRefundAsync(RefundRequest refund, CancellationToken cancellationToken = default) - { - return context.RefundRequests.AddAsync(refund, cancellationToken).AsTask(); - } - - /// - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - { - return context.SaveChangesAsync(cancellationToken); - } - - /// - public Task UpdateOrderAsync(Order order, CancellationToken cancellationToken = default) - { - context.Orders.Update(order); - return Task.CompletedTask; - } - - /// - public async Task DeleteOrderAsync(long orderId, long tenantId, CancellationToken cancellationToken = default) - { - var items = await context.OrderItems - .Where(x => x.TenantId == tenantId && x.OrderId == orderId) - .ToListAsync(cancellationToken); - if (items.Count > 0) - { - context.OrderItems.RemoveRange(items); - } - - var histories = await context.OrderStatusHistories - .Where(x => x.TenantId == tenantId && x.OrderId == orderId) - .ToListAsync(cancellationToken); - if (histories.Count > 0) - { - context.OrderStatusHistories.RemoveRange(histories); - } - - var refunds = await context.RefundRequests - .Where(x => x.TenantId == tenantId && x.OrderId == orderId) - .ToListAsync(cancellationToken); - if (refunds.Count > 0) - { - context.RefundRequests.RemoveRange(refunds); - } - - var existing = await context.Orders - .Where(x => x.TenantId == tenantId && x.Id == orderId) - .FirstOrDefaultAsync(cancellationToken); - if (existing == null) - { - return; - } - - context.Orders.Remove(existing); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfPaymentRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfPaymentRepository.cs deleted file mode 100644 index 1b6ea8d..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfPaymentRepository.cs +++ /dev/null @@ -1,110 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Payments.Entities; -using TakeoutSaaS.Domain.Payments.Enums; -using TakeoutSaaS.Domain.Payments.Repositories; -using TakeoutSaaS.Infrastructure.App.Persistence; - -namespace TakeoutSaaS.Infrastructure.App.Repositories; - -/// -/// 支付记录的 EF Core 仓储实现。 -/// -/// -/// 初始化仓储。 -/// -public sealed class EfPaymentRepository(TakeoutAppDbContext context) : IPaymentRepository -{ - /// - public Task FindByIdAsync(long paymentId, long tenantId, CancellationToken cancellationToken = default) - { - return context.PaymentRecords - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.Id == paymentId) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public Task FindByOrderIdAsync(long orderId, long tenantId, CancellationToken cancellationToken = default) - { - return context.PaymentRecords - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.OrderId == orderId) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public async Task> GetRefundsAsync(long paymentId, long tenantId, CancellationToken cancellationToken = default) - { - var refunds = await context.PaymentRefundRecords - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.PaymentRecordId == paymentId) - .OrderByDescending(x => x.CreatedAt) - .ToListAsync(cancellationToken); - - return refunds; - } - - /// - public Task AddPaymentAsync(PaymentRecord payment, CancellationToken cancellationToken = default) - { - return context.PaymentRecords.AddAsync(payment, cancellationToken).AsTask(); - } - - /// - public Task AddRefundAsync(PaymentRefundRecord refund, CancellationToken cancellationToken = default) - { - return context.PaymentRefundRecords.AddAsync(refund, cancellationToken).AsTask(); - } - - /// - public async Task> SearchAsync(long tenantId, PaymentStatus? status, CancellationToken cancellationToken = default) - { - var query = context.PaymentRecords - .AsNoTracking() - .Where(x => x.TenantId == tenantId); - - if (status.HasValue) - { - query = query.Where(x => x.Status == status.Value); - } - - return await query - .OrderByDescending(x => x.CreatedAt) - .ToListAsync(cancellationToken); - } - - /// - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - { - return context.SaveChangesAsync(cancellationToken); - } - - /// - public Task UpdatePaymentAsync(PaymentRecord payment, CancellationToken cancellationToken = default) - { - context.PaymentRecords.Update(payment); - return Task.CompletedTask; - } - - /// - public async Task DeletePaymentAsync(long paymentId, long tenantId, CancellationToken cancellationToken = default) - { - var refunds = await context.PaymentRefundRecords - .Where(x => x.TenantId == tenantId && x.PaymentRecordId == paymentId) - .ToListAsync(cancellationToken); - if (refunds.Count > 0) - { - context.PaymentRefundRecords.RemoveRange(refunds); - } - - var existing = await context.PaymentRecords - .Where(x => x.TenantId == tenantId && x.Id == paymentId) - .FirstOrDefaultAsync(cancellationToken); - if (existing == null) - { - return; - } - - context.PaymentRecords.Remove(existing); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfProductRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfProductRepository.cs deleted file mode 100644 index 5b49b68..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfProductRepository.cs +++ /dev/null @@ -1,511 +0,0 @@ -using System; -using System.Linq; -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Products.Entities; -using TakeoutSaaS.Domain.Products.Enums; -using TakeoutSaaS.Domain.Products.Repositories; -using TakeoutSaaS.Infrastructure.App.Persistence; - -namespace TakeoutSaaS.Infrastructure.App.Repositories; - -/// -/// 商品聚合的 EF Core 仓储实现。 -/// -/// -/// 初始化仓储。 -/// -public sealed class EfProductRepository(TakeoutAppDbContext context) : IProductRepository -{ - /// - public Task FindByIdAsync(long productId, long tenantId, CancellationToken cancellationToken = default) - { - return context.Products - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.Id == productId) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public async Task> SearchAsync(long tenantId, long? storeId, long? categoryId, ProductStatus? status, CancellationToken cancellationToken = default, DateTime? updatedAfter = null) - { - var query = context.Products - .AsNoTracking() - .Where(x => x.TenantId == tenantId); - - if (storeId.HasValue) - { - query = query.Where(x => x.StoreId == storeId.Value); - } - - if (categoryId.HasValue) - { - query = query.Where(x => x.CategoryId == categoryId.Value); - } - - if (status.HasValue) - { - query = query.Where(x => x.Status == status.Value); - } - - if (updatedAfter.HasValue) - { - query = query.Where(x => (x.UpdatedAt ?? x.CreatedAt) >= updatedAfter.Value); - } - - var products = await query - .OrderBy(x => x.Name) - .ToListAsync(cancellationToken); - - return products; - } - - /// - public async Task> GetCategoriesAsync(long tenantId, CancellationToken cancellationToken = default) - { - var categories = await context.ProductCategories - .AsNoTracking() - .Where(x => x.TenantId == tenantId) - .OrderBy(x => x.SortOrder) - .ToListAsync(cancellationToken); - - return categories; - } - - /// - public async Task> GetCategoriesByStoreAsync(long tenantId, long storeId, bool onlyEnabled = true, CancellationToken cancellationToken = default) - { - var query = context.ProductCategories - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.StoreId == storeId); - if (onlyEnabled) - { - query = query.Where(x => x.IsEnabled); - } - var categories = await query - .OrderBy(x => x.SortOrder) - .ToListAsync(cancellationToken); - return categories; - } - - /// - public async Task> GetSkusAsync(long productId, long tenantId, CancellationToken cancellationToken = default) - { - var skus = await context.ProductSkus - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.ProductId == productId) - .OrderBy(x => x.SortOrder) - .ToListAsync(cancellationToken); - - return skus; - } - - /// - public async Task> GetSkusByProductIdsAsync(IReadOnlyCollection productIds, long tenantId, CancellationToken cancellationToken = default) - { - if (productIds.Count == 0) - { - return Array.Empty(); - } - var skus = await context.ProductSkus - .AsNoTracking() - .Where(x => x.TenantId == tenantId && productIds.Contains(x.ProductId)) - .OrderBy(x => x.SortOrder) - .ToListAsync(cancellationToken); - return skus; - } - - /// - public async Task> GetAddonGroupsAsync(long productId, long tenantId, CancellationToken cancellationToken = default) - { - var groups = await context.ProductAddonGroups - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.ProductId == productId) - .OrderBy(x => x.SortOrder) - .ToListAsync(cancellationToken); - - return groups; - } - - /// - public async Task> GetAddonGroupsByProductIdsAsync(IReadOnlyCollection productIds, long tenantId, CancellationToken cancellationToken = default) - { - if (productIds.Count == 0) - { - return Array.Empty(); - } - var groups = await context.ProductAddonGroups - .AsNoTracking() - .Where(x => x.TenantId == tenantId && productIds.Contains(x.ProductId)) - .OrderBy(x => x.SortOrder) - .ToListAsync(cancellationToken); - return groups; - } - - /// - public async Task> GetAddonOptionsAsync(long productId, long tenantId, CancellationToken cancellationToken = default) - { - var groupIds = await context.ProductAddonGroups - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.ProductId == productId) - .Select(x => x.Id) - .ToListAsync(cancellationToken); - - if (groupIds.Count == 0) - { - return Array.Empty(); - } - - var options = await context.ProductAddonOptions - .AsNoTracking() - .Where(x => x.TenantId == tenantId && groupIds.Contains(x.AddonGroupId)) - .OrderBy(x => x.SortOrder) - .ToListAsync(cancellationToken); - - return options; - } - - /// - public async Task> GetAddonOptionsByGroupIdsAsync(IReadOnlyCollection addonGroupIds, long tenantId, CancellationToken cancellationToken = default) - { - if (addonGroupIds.Count == 0) - { - return Array.Empty(); - } - var options = await context.ProductAddonOptions - .AsNoTracking() - .Where(x => x.TenantId == tenantId && addonGroupIds.Contains(x.AddonGroupId)) - .OrderBy(x => x.SortOrder) - .ToListAsync(cancellationToken); - return options; - } - - /// - public async Task> GetAttributeGroupsAsync(long productId, long tenantId, CancellationToken cancellationToken = default) - { - var groups = await context.ProductAttributeGroups - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.ProductId == productId) - .OrderBy(x => x.SortOrder) - .ToListAsync(cancellationToken); - - return groups; - } - - /// - public async Task> GetAttributeGroupsByProductIdsAsync(IReadOnlyCollection productIds, long tenantId, CancellationToken cancellationToken = default) - { - if (productIds.Count == 0) - { - return Array.Empty(); - } - var groups = await context.ProductAttributeGroups - .AsNoTracking() - .Where(x => x.TenantId == tenantId && productIds.Contains(x.ProductId)) - .OrderBy(x => x.SortOrder) - .ToListAsync(cancellationToken); - return groups; - } - - /// - public async Task> GetAttributeOptionsAsync(long productId, long tenantId, CancellationToken cancellationToken = default) - { - var groupIds = await context.ProductAttributeGroups - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.ProductId == productId) - .Select(x => x.Id) - .ToListAsync(cancellationToken); - - if (groupIds.Count == 0) - { - return Array.Empty(); - } - - var options = await context.ProductAttributeOptions - .AsNoTracking() - .Where(x => x.TenantId == tenantId && groupIds.Contains(x.AttributeGroupId)) - .OrderBy(x => x.SortOrder) - .ToListAsync(cancellationToken); - - return options; - } - - /// - public async Task> GetAttributeOptionsByGroupIdsAsync(IReadOnlyCollection attributeGroupIds, long tenantId, CancellationToken cancellationToken = default) - { - if (attributeGroupIds.Count == 0) - { - return Array.Empty(); - } - var options = await context.ProductAttributeOptions - .AsNoTracking() - .Where(x => x.TenantId == tenantId && attributeGroupIds.Contains(x.AttributeGroupId)) - .OrderBy(x => x.SortOrder) - .ToListAsync(cancellationToken); - return options; - } - - /// - public async Task> GetMediaAssetsAsync(long productId, long tenantId, CancellationToken cancellationToken = default) - { - var assets = await context.ProductMediaAssets - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.ProductId == productId) - .OrderBy(x => x.SortOrder) - .ToListAsync(cancellationToken); - - return assets; - } - - /// - public async Task> GetMediaAssetsByProductIdsAsync(IReadOnlyCollection productIds, long tenantId, CancellationToken cancellationToken = default) - { - if (productIds.Count == 0) - { - return Array.Empty(); - } - var assets = await context.ProductMediaAssets - .AsNoTracking() - .Where(x => x.TenantId == tenantId && productIds.Contains(x.ProductId)) - .OrderBy(x => x.SortOrder) - .ToListAsync(cancellationToken); - return assets; - } - - /// - public async Task> GetPricingRulesAsync(long productId, long tenantId, CancellationToken cancellationToken = default) - { - var rules = await context.ProductPricingRules - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.ProductId == productId) - .OrderBy(x => x.SortOrder) - .ToListAsync(cancellationToken); - - return rules; - } - - /// - public async Task> GetPricingRulesByProductIdsAsync(IReadOnlyCollection productIds, long tenantId, CancellationToken cancellationToken = default) - { - if (productIds.Count == 0) - { - return Array.Empty(); - } - var rules = await context.ProductPricingRules - .AsNoTracking() - .Where(x => x.TenantId == tenantId && productIds.Contains(x.ProductId)) - .OrderBy(x => x.SortOrder) - .ToListAsync(cancellationToken); - return rules; - } - - /// - public Task AddCategoryAsync(ProductCategory category, CancellationToken cancellationToken = default) - { - return context.ProductCategories.AddAsync(category, cancellationToken).AsTask(); - } - - /// - public Task AddProductAsync(Product product, CancellationToken cancellationToken = default) - { - return context.Products.AddAsync(product, cancellationToken).AsTask(); - } - - /// - public Task AddSkusAsync(IEnumerable skus, CancellationToken cancellationToken = default) - { - return context.ProductSkus.AddRangeAsync(skus, cancellationToken); - } - - /// - public Task AddAddonGroupsAsync(IEnumerable groups, IEnumerable options, CancellationToken cancellationToken = default) - { - var addGroupsTask = context.ProductAddonGroups.AddRangeAsync(groups, cancellationToken); - var addOptionsTask = context.ProductAddonOptions.AddRangeAsync(options, cancellationToken); - return Task.WhenAll(addGroupsTask, addOptionsTask); - } - - /// - public Task AddAttributeGroupsAsync(IEnumerable groups, IEnumerable options, CancellationToken cancellationToken = default) - { - var addGroupsTask = context.ProductAttributeGroups.AddRangeAsync(groups, cancellationToken); - var addOptionsTask = context.ProductAttributeOptions.AddRangeAsync(options, cancellationToken); - return Task.WhenAll(addGroupsTask, addOptionsTask); - } - - /// - public Task AddMediaAssetsAsync(IEnumerable assets, CancellationToken cancellationToken = default) - { - return context.ProductMediaAssets.AddRangeAsync(assets, cancellationToken); - } - - /// - public Task AddPricingRulesAsync(IEnumerable rules, CancellationToken cancellationToken = default) - { - return context.ProductPricingRules.AddRangeAsync(rules, cancellationToken); - } - - /// - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - { - return context.SaveChangesAsync(cancellationToken); - } - - /// - public Task UpdateProductAsync(Product product, CancellationToken cancellationToken = default) - { - context.Products.Update(product); - return Task.CompletedTask; - } - - /// - public async Task DeleteProductAsync(long productId, long tenantId, CancellationToken cancellationToken = default) - { - await RemovePricingRulesAsync(productId, tenantId, cancellationToken); - await RemoveMediaAssetsAsync(productId, tenantId, cancellationToken); - await RemoveAttributeGroupsAsync(productId, tenantId, cancellationToken); - await RemoveAddonGroupsAsync(productId, tenantId, cancellationToken); - await RemoveSkusAsync(productId, tenantId, cancellationToken); - - var existing = await context.Products - .Where(x => x.TenantId == tenantId && x.Id == productId) - .FirstOrDefaultAsync(cancellationToken); - - if (existing == null) - { - return; - } - - context.Products.Remove(existing); - } - - /// - public Task UpdateCategoryAsync(ProductCategory category, CancellationToken cancellationToken = default) - { - context.ProductCategories.Update(category); - return Task.CompletedTask; - } - - /// - public async Task DeleteCategoryAsync(long categoryId, long tenantId, CancellationToken cancellationToken = default) - { - var existing = await context.ProductCategories - .Where(x => x.TenantId == tenantId && x.Id == categoryId) - .FirstOrDefaultAsync(cancellationToken); - - if (existing == null) - { - return; - } - - context.ProductCategories.Remove(existing); - } - - /// - public async Task RemoveSkusAsync(long productId, long tenantId, CancellationToken cancellationToken = default) - { - var skus = await context.ProductSkus - .Where(x => x.TenantId == tenantId && x.ProductId == productId) - .ToListAsync(cancellationToken); - - if (skus.Count == 0) - { - return; - } - - context.ProductSkus.RemoveRange(skus); - } - - /// - public async Task RemoveAddonGroupsAsync(long productId, long tenantId, CancellationToken cancellationToken = default) - { - var groupIds = await context.ProductAddonGroups - .Where(x => x.TenantId == tenantId && x.ProductId == productId) - .Select(x => x.Id) - .ToListAsync(cancellationToken); - - if (groupIds.Count == 0) - { - return; - } - - var options = await context.ProductAddonOptions - .Where(x => x.TenantId == tenantId && groupIds.Contains(x.AddonGroupId)) - .ToListAsync(cancellationToken); - - if (options.Count > 0) - { - context.ProductAddonOptions.RemoveRange(options); - } - - var groups = await context.ProductAddonGroups - .Where(x => groupIds.Contains(x.Id)) - .ToListAsync(cancellationToken); - - if (groups.Count > 0) - { - context.ProductAddonGroups.RemoveRange(groups); - } - } - - /// - public async Task RemoveAttributeGroupsAsync(long productId, long tenantId, CancellationToken cancellationToken = default) - { - var groupIds = await context.ProductAttributeGroups - .Where(x => x.TenantId == tenantId && x.ProductId == productId) - .Select(x => x.Id) - .ToListAsync(cancellationToken); - - if (groupIds.Count == 0) - { - return; - } - - var options = await context.ProductAttributeOptions - .Where(x => x.TenantId == tenantId && groupIds.Contains(x.AttributeGroupId)) - .ToListAsync(cancellationToken); - - if (options.Count > 0) - { - context.ProductAttributeOptions.RemoveRange(options); - } - - var groups = await context.ProductAttributeGroups - .Where(x => groupIds.Contains(x.Id)) - .ToListAsync(cancellationToken); - - if (groups.Count > 0) - { - context.ProductAttributeGroups.RemoveRange(groups); - } - } - - /// - public async Task RemoveMediaAssetsAsync(long productId, long tenantId, CancellationToken cancellationToken = default) - { - var assets = await context.ProductMediaAssets - .Where(x => x.TenantId == tenantId && x.ProductId == productId) - .ToListAsync(cancellationToken); - - if (assets.Count == 0) - { - return; - } - - context.ProductMediaAssets.RemoveRange(assets); - } - - /// - public async Task RemovePricingRulesAsync(long productId, long tenantId, CancellationToken cancellationToken = default) - { - var rules = await context.ProductPricingRules - .Where(x => x.TenantId == tenantId && x.ProductId == productId) - .ToListAsync(cancellationToken); - - if (rules.Count == 0) - { - return; - } - - context.ProductPricingRules.RemoveRange(rules); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfQuotaPackageRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfQuotaPackageRepository.cs deleted file mode 100644 index 1299a31..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfQuotaPackageRepository.cs +++ /dev/null @@ -1,166 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Infrastructure.App.Persistence; - -namespace TakeoutSaaS.Infrastructure.App.Repositories; - -/// -/// EF 配额包仓储实现。 -/// -public sealed class EfQuotaPackageRepository(TakeoutAppDbContext context) : IQuotaPackageRepository -{ - #region 配额包定义 - - /// - public Task FindByIdAsync(long id, CancellationToken cancellationToken = default) - { - return context.QuotaPackages - .FirstOrDefaultAsync(x => x.Id == id && x.DeletedAt == null, cancellationToken); - } - - /// - public async Task<(IReadOnlyList Items, int Total)> SearchPagedAsync( - TenantQuotaType? quotaType, - bool? isActive, - int page, - int pageSize, - CancellationToken cancellationToken = default) - { - var query = context.QuotaPackages.AsNoTracking() - .Where(x => x.DeletedAt == null); - - if (quotaType.HasValue) - { - query = query.Where(x => x.QuotaType == quotaType.Value); - } - - if (isActive.HasValue) - { - query = query.Where(x => x.IsActive == isActive.Value); - } - - var total = await query.CountAsync(cancellationToken); - - var items = await query - .OrderBy(x => x.SortOrder) - .ThenBy(x => x.CreatedAt) - .Skip((page - 1) * pageSize) - .Take(pageSize) - .ToListAsync(cancellationToken); - - return (items, total); - } - - /// - public Task AddAsync(QuotaPackage quotaPackage, CancellationToken cancellationToken = default) - { - return context.QuotaPackages.AddAsync(quotaPackage, cancellationToken).AsTask(); - } - - /// - public Task UpdateAsync(QuotaPackage quotaPackage, CancellationToken cancellationToken = default) - { - context.QuotaPackages.Update(quotaPackage); - return Task.CompletedTask; - } - - /// - public async Task SoftDeleteAsync(long id, CancellationToken cancellationToken = default) - { - var quotaPackage = await context.QuotaPackages - .FirstOrDefaultAsync(x => x.Id == id && x.DeletedAt == null, cancellationToken); - - if (quotaPackage == null) - { - return false; - } - - quotaPackage.DeletedAt = DateTime.UtcNow; - return true; - } - - #endregion - - #region 配额包购买记录 - - /// - public async Task<(IReadOnlyList<(TenantQuotaPackagePurchase Purchase, QuotaPackage Package)> Items, int Total)> GetPurchasesPagedAsync( - long tenantId, - int page, - int pageSize, - CancellationToken cancellationToken = default) - { - var query = context.TenantQuotaPackagePurchases - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.DeletedAt == null); - - var total = await query.CountAsync(cancellationToken); - - var items = await query - .OrderByDescending(x => x.PurchasedAt) - .Skip((page - 1) * pageSize) - .Take(pageSize) - .Join(context.QuotaPackages.AsNoTracking(), - purchase => purchase.QuotaPackageId, - package => package.Id, - (purchase, package) => new { Purchase = purchase, Package = package }) - .ToListAsync(cancellationToken); - - return (items.Select(x => (x.Purchase, x.Package)).ToList(), total); - } - - /// - public Task AddPurchaseAsync(TenantQuotaPackagePurchase purchase, CancellationToken cancellationToken = default) - { - return context.TenantQuotaPackagePurchases.AddAsync(purchase, cancellationToken).AsTask(); - } - - #endregion - - #region 配额使用情况 - - /// - public async Task> GetUsageByTenantAsync( - long tenantId, - TenantQuotaType? quotaType, - CancellationToken cancellationToken = default) - { - var query = context.TenantQuotaUsages - .AsNoTracking() - .Where(x => x.TenantId == tenantId); - - if (quotaType.HasValue) - { - query = query.Where(x => x.QuotaType == quotaType.Value); - } - - return await query.ToListAsync(cancellationToken); - } - - /// - public Task FindUsageAsync( - long tenantId, - TenantQuotaType quotaType, - CancellationToken cancellationToken = default) - { - return context.TenantQuotaUsages - .FirstOrDefaultAsync(x => x.TenantId == tenantId && x.QuotaType == quotaType, cancellationToken); - } - - /// - public Task UpdateUsageAsync(TenantQuotaUsage usage, CancellationToken cancellationToken = default) - { - context.TenantQuotaUsages.Update(usage); - return Task.CompletedTask; - } - - #endregion - - /// - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - { - return context.SaveChangesAsync(cancellationToken); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfStatisticsRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfStatisticsRepository.cs deleted file mode 100644 index 694fdb7..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfStatisticsRepository.cs +++ /dev/null @@ -1,116 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Infrastructure.App.Persistence; - -namespace TakeoutSaaS.Infrastructure.App.Repositories; - -/// -/// 统计数据仓储实现。 -/// -public sealed class EfStatisticsRepository(TakeoutAppDbContext dbContext) : IStatisticsRepository -{ - #region 订阅统计 - - /// - public async Task> GetAllSubscriptionsAsync(CancellationToken cancellationToken = default) - { - return await dbContext.TenantSubscriptions - .AsNoTracking() - .ToListAsync(cancellationToken); - } - - /// - public async Task> GetExpiringSubscriptionsAsync( - int daysAhead, - bool onlyWithoutAutoRenew, - CancellationToken cancellationToken = default) - { - var now = DateTime.UtcNow; - var targetDate = now.AddDays(daysAhead); - - // 构建基础查询 - var query = dbContext.TenantSubscriptions - .AsNoTracking() - .Where(s => s.Status == SubscriptionStatus.Active - && s.EffectiveTo >= now - && s.EffectiveTo <= targetDate); - - // 如果只查询未开启自动续费的 - if (onlyWithoutAutoRenew) - { - query = query.Where(s => !s.AutoRenew); - } - - // 连接租户和套餐信息 - var result = await query - .Join( - dbContext.Tenants, - sub => sub.TenantId, - tenant => tenant.Id, - (sub, tenant) => new { Subscription = sub, Tenant = tenant } - ) - .Join( - dbContext.TenantPackages, - combined => combined.Subscription.TenantPackageId, - package => package.Id, - (combined, package) => new ExpiringSubscriptionInfo - { - Subscription = combined.Subscription, - TenantName = combined.Tenant.Name, - PackageName = package.Name - } - ) - .OrderBy(x => x.Subscription.EffectiveTo) - .ToListAsync(cancellationToken); - - return result; - } - - #endregion - - #region 收入统计 - - /// - public async Task> GetPaidBillsAsync(CancellationToken cancellationToken = default) - { - return await dbContext.TenantBillingStatements - .AsNoTracking() - .Where(b => b.Status == TenantBillingStatus.Paid) - .ToListAsync(cancellationToken); - } - - #endregion - - #region 配额使用排行 - - /// - public async Task> GetQuotaUsageRankingAsync( - TenantQuotaType quotaType, - int topN, - CancellationToken cancellationToken = default) - { - return await dbContext.TenantQuotaUsages - .AsNoTracking() - .Where(q => q.QuotaType == quotaType && q.LimitValue > 0) - .Join( - dbContext.Tenants, - quota => quota.TenantId, - tenant => tenant.Id, - (quota, tenant) => new QuotaUsageRankInfo - { - TenantId = quota.TenantId, - TenantName = tenant.Name, - UsedValue = quota.UsedValue, - LimitValue = quota.LimitValue, - UsagePercentage = quota.LimitValue > 0 ? (quota.UsedValue / quota.LimitValue * 100) : 0 - } - ) - .OrderByDescending(x => x.UsagePercentage) - .Take(topN) - .ToListAsync(cancellationToken); - } - - #endregion -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfStoreRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfStoreRepository.cs deleted file mode 100644 index 72952f1..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfStoreRepository.cs +++ /dev/null @@ -1,645 +0,0 @@ -using System; -using System.Linq; -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Stores.Entities; -using TakeoutSaaS.Domain.Stores.Enums; -using TakeoutSaaS.Domain.Stores.Repositories; -using TakeoutSaaS.Infrastructure.App.Persistence; - -namespace TakeoutSaaS.Infrastructure.App.Repositories; - -/// -/// 门店聚合的 EF Core 仓储实现。 -/// -/// -/// 初始化仓储。 -/// -public sealed class EfStoreRepository(TakeoutAppDbContext context) : IStoreRepository -{ - /// - public Task FindByIdAsync(long storeId, long tenantId, CancellationToken cancellationToken = default) - { - return context.Stores - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.Id == storeId) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public async Task> GetByMerchantIdAsync(long merchantId, long tenantId, CancellationToken cancellationToken = default) - { - return await context.Stores - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.MerchantId == merchantId) - .OrderBy(x => x.Name) - .ToListAsync(cancellationToken); - } - - /// - public async Task> SearchAsync( - long tenantId, - long? merchantId, - StoreStatus? status, - StoreAuditStatus? auditStatus, - StoreBusinessStatus? businessStatus, - StoreOwnershipType? ownershipType, - string? keyword, - CancellationToken cancellationToken = default) - { - var query = context.Stores - .AsNoTracking() - .Where(x => x.TenantId == tenantId); - - if (merchantId.HasValue) - { - query = query.Where(x => x.MerchantId == merchantId.Value); - } - - if (status.HasValue) - { - query = query.Where(x => x.Status == status.Value); - } - - if (auditStatus.HasValue) - { - query = query.Where(x => x.AuditStatus == auditStatus.Value); - } - - if (businessStatus.HasValue) - { - query = query.Where(x => x.BusinessStatus == businessStatus.Value); - } - - if (ownershipType.HasValue) - { - query = query.Where(x => x.OwnershipType == ownershipType.Value); - } - - if (!string.IsNullOrWhiteSpace(keyword)) - { - var trimmed = keyword.Trim(); - query = query.Where(x => x.Name.Contains(trimmed) || x.Code.Contains(trimmed)); - } - - var stores = await query - .OrderBy(x => x.Name) - .ToListAsync(cancellationToken); - - return stores; - } - - /// - public async Task ExistsStoreWithinDistanceAsync( - long merchantId, - long tenantId, - double longitude, - double latitude, - double distanceMeters, - CancellationToken cancellationToken = default) - { - // 1. 校验距离阈值 - if (distanceMeters <= 0) - { - return false; - } - - // 2. (空行后) 拉取候选坐标 - var coordinates = await context.Stores - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.MerchantId == merchantId) - .Where(x => x.Longitude.HasValue && x.Latitude.HasValue) - .Select(x => new { Longitude = x.Longitude!.Value, Latitude = x.Latitude!.Value }) - .ToListAsync(cancellationToken); - - // 3. (空行后) 计算距离并判断是否命中 - foreach (var coordinate in coordinates) - { - var distance = CalculateDistanceMeters(latitude, longitude, coordinate.Latitude, coordinate.Longitude); - if (distance <= distanceMeters) - { - return true; - } - } - - // 4. (空行后) 返回未命中结果 - return false; - } - - /// - public async Task> GetStoreCountsAsync(long tenantId, IReadOnlyCollection merchantIds, CancellationToken cancellationToken = default) - { - if (merchantIds.Count == 0) - { - return new Dictionary(); - } - - var query = context.Stores - .AsNoTracking() - .Where(x => x.TenantId == tenantId); - - return await query - .Where(x => merchantIds.Contains(x.MerchantId)) - .GroupBy(x => x.MerchantId) - .Select(group => new { group.Key, Count = group.Count() }) - .ToDictionaryAsync(x => x.Key, x => x.Count, cancellationToken); - } - - /// - public async Task> GetBusinessHoursAsync(long storeId, long tenantId, CancellationToken cancellationToken = default) - { - var hours = await context.StoreBusinessHours - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.StoreId == storeId) - .OrderBy(x => x.DayOfWeek) - .ThenBy(x => x.StartTime) - .ToListAsync(cancellationToken); - - return hours; - } - - /// - public Task GetStoreFeeAsync(long storeId, long tenantId, CancellationToken cancellationToken = default) - { - return context.StoreFees - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.StoreId == storeId) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public Task AddStoreFeeAsync(StoreFee storeFee, CancellationToken cancellationToken = default) - { - return context.StoreFees.AddAsync(storeFee, cancellationToken).AsTask(); - } - - /// - public Task UpdateStoreFeeAsync(StoreFee storeFee, CancellationToken cancellationToken = default) - { - context.StoreFees.Update(storeFee); - return Task.CompletedTask; - } - - /// - public async Task> GetQualificationsAsync(long storeId, long tenantId, CancellationToken cancellationToken = default) - { - var qualifications = await context.StoreQualifications - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.StoreId == storeId) - .OrderBy(x => x.SortOrder) - .ThenBy(x => x.QualificationType) - .ToListAsync(cancellationToken); - return qualifications; - } - - /// - public Task FindQualificationByIdAsync(long qualificationId, long tenantId, CancellationToken cancellationToken = default) - { - return context.StoreQualifications - .Where(x => x.TenantId == tenantId && x.Id == qualificationId) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public Task AddQualificationAsync(StoreQualification qualification, CancellationToken cancellationToken = default) - { - return context.StoreQualifications.AddAsync(qualification, cancellationToken).AsTask(); - } - - /// - public Task UpdateQualificationAsync(StoreQualification qualification, CancellationToken cancellationToken = default) - { - context.StoreQualifications.Update(qualification); - return Task.CompletedTask; - } - - /// - public async Task DeleteQualificationAsync(long qualificationId, long tenantId, CancellationToken cancellationToken = default) - { - var existing = await context.StoreQualifications - .Where(x => x.TenantId == tenantId && x.Id == qualificationId) - .FirstOrDefaultAsync(cancellationToken); - - if (existing != null) - { - context.StoreQualifications.Remove(existing); - } - } - - /// - public Task AddAuditRecordAsync(StoreAuditRecord record, CancellationToken cancellationToken = default) - { - return context.StoreAuditRecords.AddAsync(record, cancellationToken).AsTask(); - } - - /// - public async Task> GetAuditRecordsAsync(long storeId, long tenantId, CancellationToken cancellationToken = default) - { - var records = await context.StoreAuditRecords - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.StoreId == storeId) - .OrderByDescending(x => x.CreatedAt) - .ToListAsync(cancellationToken); - return records; - } - - /// - public Task FindBusinessHourByIdAsync(long businessHourId, long tenantId, CancellationToken cancellationToken = default) - { - return context.StoreBusinessHours - .Where(x => x.TenantId == tenantId && x.Id == businessHourId) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public async Task> GetDeliveryZonesAsync(long storeId, long tenantId, CancellationToken cancellationToken = default) - { - var zones = await context.StoreDeliveryZones - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.StoreId == storeId) - .OrderBy(x => x.SortOrder) - .ToListAsync(cancellationToken); - - return zones; - } - - /// - public Task FindDeliveryZoneByIdAsync(long deliveryZoneId, long tenantId, CancellationToken cancellationToken = default) - { - return context.StoreDeliveryZones - .Where(x => x.TenantId == tenantId && x.Id == deliveryZoneId) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public async Task> GetHolidaysAsync(long storeId, long tenantId, CancellationToken cancellationToken = default) - { - var holidays = await context.StoreHolidays - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.StoreId == storeId) - .OrderBy(x => x.Date) - .ToListAsync(cancellationToken); - - return holidays; - } - - /// - public Task FindHolidayByIdAsync(long holidayId, long tenantId, CancellationToken cancellationToken = default) - { - return context.StoreHolidays - .Where(x => x.TenantId == tenantId && x.Id == holidayId) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public async Task> GetTableAreasAsync(long storeId, long tenantId, CancellationToken cancellationToken = default) - { - var areas = await context.StoreTableAreas - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.StoreId == storeId) - .OrderBy(x => x.SortOrder) - .ToListAsync(cancellationToken); - - return areas; - } - - /// - public Task FindTableAreaByIdAsync(long areaId, long tenantId, CancellationToken cancellationToken = default) - { - return context.StoreTableAreas - .Where(x => x.TenantId == tenantId && x.Id == areaId) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public async Task> GetTablesAsync(long storeId, long tenantId, CancellationToken cancellationToken = default) - { - var tables = await context.StoreTables - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.StoreId == storeId) - .OrderBy(x => x.TableCode) - .ToListAsync(cancellationToken); - - return tables; - } - - /// - public Task FindTableByIdAsync(long tableId, long tenantId, CancellationToken cancellationToken = default) - { - return context.StoreTables - .Where(x => x.TenantId == tenantId && x.Id == tableId) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public Task FindTableByCodeAsync(string tableCode, long tenantId, CancellationToken cancellationToken = default) - { - return context.StoreTables - .Where(x => x.TenantId == tenantId && x.TableCode == tableCode) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public Task GetPickupSettingAsync(long storeId, long tenantId, CancellationToken cancellationToken = default) - { - return context.StorePickupSettings - .Where(x => x.TenantId == tenantId && x.StoreId == storeId) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public Task AddPickupSettingAsync(StorePickupSetting setting, CancellationToken cancellationToken = default) - { - return context.StorePickupSettings.AddAsync(setting, cancellationToken).AsTask(); - } - - /// - public Task UpdatePickupSettingAsync(StorePickupSetting setting, CancellationToken cancellationToken = default) - { - context.StorePickupSettings.Update(setting); - return Task.CompletedTask; - } - - /// - public async Task> GetPickupSlotsAsync(long storeId, long tenantId, CancellationToken cancellationToken = default) - { - var slots = await context.StorePickupSlots - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.StoreId == storeId) - .OrderBy(x => x.StartTime) - .ToListAsync(cancellationToken); - return slots; - } - - /// - public Task FindPickupSlotByIdAsync(long slotId, long tenantId, CancellationToken cancellationToken = default) - { - return context.StorePickupSlots - .Where(x => x.TenantId == tenantId && x.Id == slotId) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public Task AddPickupSlotsAsync(IEnumerable slots, CancellationToken cancellationToken = default) - { - return context.StorePickupSlots.AddRangeAsync(slots, cancellationToken); - } - - /// - public Task UpdatePickupSlotAsync(StorePickupSlot slot, CancellationToken cancellationToken = default) - { - context.StorePickupSlots.Update(slot); - return Task.CompletedTask; - } - - /// - public async Task> GetShiftsAsync(long storeId, long tenantId, DateTime? from = null, DateTime? to = null, CancellationToken cancellationToken = default) - { - var query = context.StoreEmployeeShifts - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.StoreId == storeId); - - if (from.HasValue) - { - query = query.Where(x => x.ShiftDate >= from.Value.Date); - } - - if (to.HasValue) - { - query = query.Where(x => x.ShiftDate <= to.Value.Date); - } - - var shifts = await query - .OrderBy(x => x.ShiftDate) - .ThenBy(x => x.StartTime) - .ToListAsync(cancellationToken); - - return shifts; - } - - /// - public Task FindShiftByIdAsync(long shiftId, long tenantId, CancellationToken cancellationToken = default) - { - return context.StoreEmployeeShifts - .Where(x => x.TenantId == tenantId && x.Id == shiftId) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public Task AddStoreAsync(Store store, CancellationToken cancellationToken = default) - { - return context.Stores.AddAsync(store, cancellationToken).AsTask(); - } - - /// - public Task AddBusinessHoursAsync(IEnumerable hours, CancellationToken cancellationToken = default) - { - return context.StoreBusinessHours.AddRangeAsync(hours, cancellationToken); - } - - /// - public Task UpdateBusinessHourAsync(StoreBusinessHour hour, CancellationToken cancellationToken = default) - { - context.StoreBusinessHours.Update(hour); - return Task.CompletedTask; - } - - /// - public Task AddDeliveryZonesAsync(IEnumerable zones, CancellationToken cancellationToken = default) - { - return context.StoreDeliveryZones.AddRangeAsync(zones, cancellationToken); - } - - /// - public Task UpdateDeliveryZoneAsync(StoreDeliveryZone zone, CancellationToken cancellationToken = default) - { - context.StoreDeliveryZones.Update(zone); - return Task.CompletedTask; - } - - /// - public Task AddHolidaysAsync(IEnumerable holidays, CancellationToken cancellationToken = default) - { - return context.StoreHolidays.AddRangeAsync(holidays, cancellationToken); - } - - /// - public Task UpdateHolidayAsync(StoreHoliday holiday, CancellationToken cancellationToken = default) - { - context.StoreHolidays.Update(holiday); - return Task.CompletedTask; - } - - /// - public Task AddTableAreasAsync(IEnumerable areas, CancellationToken cancellationToken = default) - { - return context.StoreTableAreas.AddRangeAsync(areas, cancellationToken); - } - - /// - public Task UpdateTableAreaAsync(StoreTableArea area, CancellationToken cancellationToken = default) - { - context.StoreTableAreas.Update(area); - return Task.CompletedTask; - } - - /// - public Task AddTablesAsync(IEnumerable tables, CancellationToken cancellationToken = default) - { - return context.StoreTables.AddRangeAsync(tables, cancellationToken); - } - - /// - public Task UpdateTableAsync(StoreTable table, CancellationToken cancellationToken = default) - { - context.StoreTables.Update(table); - return Task.CompletedTask; - } - - /// - public Task AddShiftsAsync(IEnumerable shifts, CancellationToken cancellationToken = default) - { - return context.StoreEmployeeShifts.AddRangeAsync(shifts, cancellationToken); - } - - /// - public Task UpdateShiftAsync(StoreEmployeeShift shift, CancellationToken cancellationToken = default) - { - context.StoreEmployeeShifts.Update(shift); - return Task.CompletedTask; - } - - /// - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - { - return context.SaveChangesAsync(cancellationToken); - } - - /// - public async Task DeleteBusinessHourAsync(long businessHourId, long tenantId, CancellationToken cancellationToken = default) - { - var existing = await context.StoreBusinessHours - .Where(x => x.TenantId == tenantId && x.Id == businessHourId) - .FirstOrDefaultAsync(cancellationToken); - - if (existing != null) - { - context.StoreBusinessHours.Remove(existing); - } - } - - /// - public async Task DeleteDeliveryZoneAsync(long deliveryZoneId, long tenantId, CancellationToken cancellationToken = default) - { - var existing = await context.StoreDeliveryZones - .Where(x => x.TenantId == tenantId && x.Id == deliveryZoneId) - .FirstOrDefaultAsync(cancellationToken); - - if (existing != null) - { - context.StoreDeliveryZones.Remove(existing); - } - } - - /// - public async Task DeleteHolidayAsync(long holidayId, long tenantId, CancellationToken cancellationToken = default) - { - var existing = await context.StoreHolidays - .Where(x => x.TenantId == tenantId && x.Id == holidayId) - .FirstOrDefaultAsync(cancellationToken); - - if (existing != null) - { - context.StoreHolidays.Remove(existing); - } - } - - /// - public async Task DeleteTableAreaAsync(long areaId, long tenantId, CancellationToken cancellationToken = default) - { - var existing = await context.StoreTableAreas - .Where(x => x.TenantId == tenantId && x.Id == areaId) - .FirstOrDefaultAsync(cancellationToken); - - if (existing != null) - { - context.StoreTableAreas.Remove(existing); - } - } - - /// - public async Task DeleteTableAsync(long tableId, long tenantId, CancellationToken cancellationToken = default) - { - var existing = await context.StoreTables - .Where(x => x.TenantId == tenantId && x.Id == tableId) - .FirstOrDefaultAsync(cancellationToken); - - if (existing != null) - { - context.StoreTables.Remove(existing); - } - } - - /// - public async Task DeletePickupSlotAsync(long slotId, long tenantId, CancellationToken cancellationToken = default) - { - var existing = await context.StorePickupSlots - .Where(x => x.TenantId == tenantId && x.Id == slotId) - .FirstOrDefaultAsync(cancellationToken); - - if (existing != null) - { - context.StorePickupSlots.Remove(existing); - } - } - - /// - public async Task DeleteShiftAsync(long shiftId, long tenantId, CancellationToken cancellationToken = default) - { - var existing = await context.StoreEmployeeShifts - .Where(x => x.TenantId == tenantId && x.Id == shiftId) - .FirstOrDefaultAsync(cancellationToken); - - if (existing != null) - { - context.StoreEmployeeShifts.Remove(existing); - } - } - - /// - public Task UpdateStoreAsync(Store store, CancellationToken cancellationToken = default) - { - context.Stores.Update(store); - return Task.CompletedTask; - } - - /// - public async Task DeleteStoreAsync(long storeId, long tenantId, CancellationToken cancellationToken = default) - { - var existing = await context.Stores - .Where(x => x.TenantId == tenantId && x.Id == storeId) - .FirstOrDefaultAsync(cancellationToken); - - if (existing == null) - { - return; - } - - context.Stores.Remove(existing); - } - - private static double CalculateDistanceMeters(double latitude1, double longitude1, double latitude2, double longitude2) - { - const double earthRadius = 6371000d; - var latRad1 = DegreesToRadians(latitude1); - var latRad2 = DegreesToRadians(latitude2); - var deltaLat = DegreesToRadians(latitude2 - latitude1); - var deltaLon = DegreesToRadians(longitude2 - longitude1); - var sinLat = Math.Sin(deltaLat / 2); - var sinLon = Math.Sin(deltaLon / 2); - var a = sinLat * sinLat + Math.Cos(latRad1) * Math.Cos(latRad2) * sinLon * sinLon; - var c = 2 * Math.Asin(Math.Min(1, Math.Sqrt(a))); - return earthRadius * c; - } - - private static double DegreesToRadians(double degrees) => degrees * (Math.PI / 180d); -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfSubscriptionRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfSubscriptionRepository.cs deleted file mode 100644 index 5168764..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfSubscriptionRepository.cs +++ /dev/null @@ -1,362 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Infrastructure.App.Persistence; -using TakeoutSaaS.Infrastructure.Logs.Persistence; - -namespace TakeoutSaaS.Infrastructure.App.Repositories; - -/// -/// 订阅管理仓储实现。 -/// -public sealed class EfSubscriptionRepository(TakeoutAppDbContext dbContext, TakeoutLogsDbContext logsContext) : ISubscriptionRepository -{ - #region 订阅查询 - - /// - public async Task FindByIdAsync( - long subscriptionId, - CancellationToken cancellationToken = default) - { - return await dbContext.TenantSubscriptions - .FirstOrDefaultAsync(s => s.Id == subscriptionId, cancellationToken); - } - - /// - public async Task> FindByIdsAsync( - IEnumerable subscriptionIds, - CancellationToken cancellationToken = default) - { - var ids = subscriptionIds.ToList(); - return await dbContext.TenantSubscriptions - .Where(s => ids.Contains(s.Id)) - .ToListAsync(cancellationToken); - } - - /// - public async Task<(IReadOnlyList Items, int Total)> SearchPagedAsync( - SubscriptionSearchFilter filter, - CancellationToken cancellationToken = default) - { - // 1. 构建基础查询 - var query = dbContext.TenantSubscriptions - .AsNoTracking() - .Join( - dbContext.Tenants, - sub => sub.TenantId, - tenant => tenant.Id, - (sub, tenant) => new { Subscription = sub, Tenant = tenant } - ) - .Join( - dbContext.TenantPackages, - combined => combined.Subscription.TenantPackageId, - package => package.Id, - (combined, package) => new { combined.Subscription, combined.Tenant, Package = package } - ) - .GroupJoin( - dbContext.TenantPackages, - combined => combined.Subscription.ScheduledPackageId, - scheduledPackage => scheduledPackage.Id, - (combined, scheduledPackages) => new { combined.Subscription, combined.Tenant, combined.Package, ScheduledPackage = scheduledPackages.FirstOrDefault() } - ); - - // 2. 应用过滤条件 - if (filter.Status.HasValue) - { - query = query.Where(x => x.Subscription.Status == filter.Status.Value); - } - - if (filter.TenantPackageId.HasValue) - { - query = query.Where(x => x.Subscription.TenantPackageId == filter.TenantPackageId.Value); - } - - if (filter.TenantId.HasValue) - { - query = query.Where(x => x.Subscription.TenantId == filter.TenantId.Value); - } - - if (!string.IsNullOrWhiteSpace(filter.TenantKeyword)) - { - var keyword = filter.TenantKeyword.Trim().ToLower(); - query = query.Where(x => x.Tenant.Name.ToLower().Contains(keyword) || x.Tenant.Code.ToLower().Contains(keyword)); - } - - if (filter.ExpiringWithinDays.HasValue) - { - var expiryDate = DateTime.UtcNow.AddDays(filter.ExpiringWithinDays.Value); - query = query.Where(x => x.Subscription.EffectiveTo <= expiryDate && x.Subscription.EffectiveTo >= DateTime.UtcNow); - } - - if (filter.AutoRenew.HasValue) - { - query = query.Where(x => x.Subscription.AutoRenew == filter.AutoRenew.Value); - } - - // 3. 获取总数 - var total = await query.CountAsync(cancellationToken); - - // 4. 排序和分页 - var items = await query - .OrderByDescending(x => x.Subscription.CreatedAt) - .Skip((filter.Page - 1) * filter.PageSize) - .Take(filter.PageSize) - .Select(x => new SubscriptionWithRelations - { - Subscription = x.Subscription, - TenantName = x.Tenant.Name, - TenantCode = x.Tenant.Code, - PackageName = x.Package.Name, - ScheduledPackageName = x.ScheduledPackage != null ? x.ScheduledPackage.Name : null - }) - .ToListAsync(cancellationToken); - - return (items, total); - } - - /// - public async Task GetDetailAsync( - long subscriptionId, - CancellationToken cancellationToken = default) - { - var result = await dbContext.TenantSubscriptions - .AsNoTracking() - .Where(s => s.Id == subscriptionId) - .Select(s => new - { - Subscription = s, - Tenant = dbContext.Tenants.FirstOrDefault(t => t.Id == s.TenantId), - Package = dbContext.TenantPackages.FirstOrDefault(p => p.Id == s.TenantPackageId), - ScheduledPackage = s.ScheduledPackageId.HasValue - ? dbContext.TenantPackages.FirstOrDefault(p => p.Id == s.ScheduledPackageId) - : null - }) - .FirstOrDefaultAsync(cancellationToken); - - if (result == null) - { - return null; - } - - return new SubscriptionDetailInfo - { - Subscription = result.Subscription, - TenantName = result.Tenant?.Name ?? "", - TenantCode = result.Tenant?.Code ?? "", - Package = result.Package, - ScheduledPackage = result.ScheduledPackage - }; - } - - /// - public async Task> FindByIdsWithTenantAsync( - IEnumerable subscriptionIds, - CancellationToken cancellationToken = default) - { - var ids = subscriptionIds.ToList(); - - return await dbContext.TenantSubscriptions - .Where(s => ids.Contains(s.Id)) - .Join( - dbContext.Tenants, - sub => sub.TenantId, - tenant => tenant.Id, - (sub, tenant) => new SubscriptionWithTenant - { - Subscription = sub, - Tenant = tenant - } - ) - .ToListAsync(cancellationToken); - } - - /// - public async Task> FindAutoRenewalCandidatesAsync( - DateTime now, - DateTime renewalThreshold, - CancellationToken cancellationToken = default) - { - // 1. 查询开启自动续费且即将到期的活跃订阅 - var query = dbContext.TenantSubscriptions - .Where(s => s.Status == SubscriptionStatus.Active - && s.AutoRenew - && s.EffectiveTo <= renewalThreshold - && s.EffectiveTo > now) - .Join( - dbContext.TenantPackages, - subscription => subscription.TenantPackageId, - package => package.Id, - (subscription, package) => new AutoRenewalCandidate - { - Subscription = subscription, - Package = package - }); - - // 2. 返回候选列表 - return await query.ToListAsync(cancellationToken); - } - - /// - public async Task> FindRenewalReminderCandidatesAsync( - DateTime startOfDay, - DateTime endOfDay, - CancellationToken cancellationToken = default) - { - // 1. 查询到期落在指定区间的订阅(且未开启自动续费) - var query = dbContext.TenantSubscriptions - .Where(s => s.Status == SubscriptionStatus.Active - && !s.AutoRenew - && s.EffectiveTo >= startOfDay - && s.EffectiveTo < endOfDay) - .Join( - dbContext.Tenants, - subscription => subscription.TenantId, - tenant => tenant.Id, - (subscription, tenant) => new { Subscription = subscription, Tenant = tenant }) - .Join( - dbContext.TenantPackages, - combined => combined.Subscription.TenantPackageId, - package => package.Id, - (combined, package) => new RenewalReminderCandidate - { - Subscription = combined.Subscription, - Tenant = combined.Tenant, - Package = package - }); - - // 2. 返回候选列表 - return await query.ToListAsync(cancellationToken); - } - - /// - public async Task> FindExpiredActiveSubscriptionsAsync( - DateTime now, - CancellationToken cancellationToken = default) - { - // 1. 查询已到期仍为 Active 的订阅 - return await dbContext.TenantSubscriptions - .Where(s => s.Status == SubscriptionStatus.Active && s.EffectiveTo < now) - .ToListAsync(cancellationToken); - } - - /// - public async Task> FindGracePeriodExpiredSubscriptionsAsync( - DateTime now, - int gracePeriodDays, - CancellationToken cancellationToken = default) - { - // 1. 查询宽限期已结束的订阅 - return await dbContext.TenantSubscriptions - .Where(s => s.Status == SubscriptionStatus.GracePeriod - && s.EffectiveTo.AddDays(gracePeriodDays) < now) - .ToListAsync(cancellationToken); - } - - #endregion - - #region 套餐查询 - - /// - public async Task FindPackageByIdAsync(long packageId, CancellationToken cancellationToken = default) - { - return await dbContext.TenantPackages - .AsNoTracking() - .FirstOrDefaultAsync(p => p.Id == packageId, cancellationToken); - } - - #endregion - - #region 订阅更新 - - /// - public Task UpdateAsync(TenantSubscription subscription, CancellationToken cancellationToken = default) - { - dbContext.TenantSubscriptions.Update(subscription); - return Task.CompletedTask; - } - - #endregion - - #region 订阅历史 - - /// - public Task AddHistoryAsync(TenantSubscriptionHistory history, CancellationToken cancellationToken = default) - { - dbContext.TenantSubscriptionHistories.Add(history); - return Task.CompletedTask; - } - - /// - public async Task> GetHistoryAsync( - long subscriptionId, - CancellationToken cancellationToken = default) - { - return await dbContext.TenantSubscriptionHistories - .AsNoTracking() - .Where(h => h.TenantSubscriptionId == subscriptionId) - .OrderByDescending(h => h.CreatedAt) - .Select(h => new SubscriptionHistoryWithPackageNames - { - History = h, - FromPackageName = dbContext.TenantPackages - .Where(p => p.Id == h.FromPackageId) - .Select(p => p.Name) - .FirstOrDefault() ?? "", - ToPackageName = dbContext.TenantPackages - .Where(p => p.Id == h.ToPackageId) - .Select(p => p.Name) - .FirstOrDefault() ?? "" - }) - .ToListAsync(cancellationToken); - } - - #endregion - - #region 配额使用 - - /// - public async Task> GetQuotaUsagesAsync( - long tenantId, - CancellationToken cancellationToken = default) - { - return await dbContext.TenantQuotaUsages - .AsNoTracking() - .Where(q => q.TenantId == tenantId) - .ToListAsync(cancellationToken); - } - - #endregion - - #region 通知 - - /// - public Task AddNotificationAsync(TenantNotification notification, CancellationToken cancellationToken = default) - { - dbContext.TenantNotifications.Add(notification); - return Task.CompletedTask; - } - - #endregion - - #region 操作日志 - - /// - public Task AddOperationLogAsync(OperationLog log, CancellationToken cancellationToken = default) - { - logsContext.OperationLogs.Add(log); - return Task.CompletedTask; - } - - #endregion - - /// - public async Task SaveChangesAsync(CancellationToken cancellationToken = default) - { - // 1. 保存业务库变更 - await dbContext.SaveChangesAsync(cancellationToken); - - // 2. 保存日志库变更 - await logsContext.SaveChangesAsync(cancellationToken); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantAnnouncementReadRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantAnnouncementReadRepository.cs deleted file mode 100644 index 23236ae..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantAnnouncementReadRepository.cs +++ /dev/null @@ -1,68 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Infrastructure.App.Persistence; - -namespace TakeoutSaaS.Infrastructure.App.Repositories; - -/// -/// EF 公告已读仓储。 -/// -public sealed class EfTenantAnnouncementReadRepository(TakeoutAppDbContext context) : ITenantAnnouncementReadRepository -{ - /// - public Task> GetByAnnouncementAsync(long tenantId, long announcementId, CancellationToken cancellationToken = default) - { - return context.TenantAnnouncementReads.AsNoTracking() - .Where(x => x.TenantId == tenantId && x.AnnouncementId == announcementId) - .OrderBy(x => x.ReadAt) - .ToListAsync(cancellationToken) - .ContinueWith(t => (IReadOnlyList)t.Result, cancellationToken); - } - - /// - public Task> GetByAnnouncementAsync(long tenantId, IEnumerable announcementIds, long? userId, CancellationToken cancellationToken = default) - { - var ids = announcementIds.Distinct().ToArray(); - if (ids.Length == 0) - { - return Task.FromResult>(Array.Empty()); - } - - var query = context.TenantAnnouncementReads.AsNoTracking() - .Where(x => x.TenantId == tenantId && ids.Contains(x.AnnouncementId)); - - if (userId.HasValue) - { - query = query.Where(x => x.UserId == userId.Value); - } - else - { - query = query.Where(x => x.UserId == null); - } - - return query - .OrderByDescending(x => x.ReadAt) - .ToListAsync(cancellationToken) - .ContinueWith(t => (IReadOnlyList)t.Result, cancellationToken); - } - - /// - public Task FindAsync(long tenantId, long announcementId, long? userId, CancellationToken cancellationToken = default) - { - return context.TenantAnnouncementReads - .FirstOrDefaultAsync(x => x.TenantId == tenantId && x.AnnouncementId == announcementId && x.UserId == userId, cancellationToken); - } - - /// - public Task AddAsync(TenantAnnouncementRead record, CancellationToken cancellationToken = default) - { - return context.TenantAnnouncementReads.AddAsync(record, cancellationToken).AsTask(); - } - - /// - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - { - return context.SaveChangesAsync(cancellationToken); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantAnnouncementRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantAnnouncementRepository.cs deleted file mode 100644 index 75ba5f8..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantAnnouncementRepository.cs +++ /dev/null @@ -1,167 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Infrastructure.App.Persistence; - -namespace TakeoutSaaS.Infrastructure.App.Repositories; - -/// -/// EF 租户公告仓储。 -/// -public sealed class EfTenantAnnouncementRepository(TakeoutAppDbContext context) : ITenantAnnouncementRepository -{ - /// - public async Task> SearchAsync( - long tenantId, - string? keyword, - AnnouncementStatus? status, - TenantAnnouncementType? type, - bool? isActive, - DateTime? effectiveFrom, - DateTime? effectiveTo, - DateTime? effectiveAt, - bool orderByPriority = false, - int? limit = null, - CancellationToken cancellationToken = default) - { - var query = context.TenantAnnouncements.AsNoTracking() - .Where(x => x.TenantId == tenantId); - - if (!string.IsNullOrWhiteSpace(keyword)) - { - var normalized = keyword.Trim(); - query = query.Where(x => - EF.Functions.ILike(x.Title, $"%{normalized}%") - || EF.Functions.ILike(x.Content, $"%{normalized}%")); - } - - if (status.HasValue) - { - query = query.Where(x => x.Status == status.Value); - } - - if (type.HasValue) - { - query = query.Where(x => x.AnnouncementType == type.Value); - } - - if (isActive.HasValue) - { - query = isActive.Value - ? query.Where(x => x.Status == AnnouncementStatus.Published) - : query.Where(x => x.Status != AnnouncementStatus.Published); - } - - if (effectiveFrom.HasValue) - { - query = query.Where(x => x.EffectiveFrom >= effectiveFrom.Value); - } - - if (effectiveTo.HasValue) - { - query = query.Where(x => x.EffectiveTo == null || x.EffectiveTo <= effectiveTo.Value); - } - - if (effectiveAt.HasValue) - { - var at = effectiveAt.Value; - query = query.Where(x => x.EffectiveFrom <= at && (x.EffectiveTo == null || x.EffectiveTo >= at)); - } - - // 应用排序(如果启用) - if (orderByPriority) - { - query = query.OrderByDescending(x => x.Priority).ThenByDescending(x => x.EffectiveFrom); - } - - // 应用限制(如果指定) - if (limit.HasValue && limit.Value > 0) - { - query = query.Take(limit.Value); - } - - return await query.ToListAsync(cancellationToken); - } - - /// - public async Task> SearchUnreadAsync( - long tenantId, - long? userId, - AnnouncementStatus? status, - bool? isActive, - DateTime? effectiveAt, - CancellationToken cancellationToken = default) - { - var announcementQuery = context.TenantAnnouncements.AsNoTracking() - .Where(x => x.TenantId == tenantId); - - if (status.HasValue) - { - announcementQuery = announcementQuery.Where(x => x.Status == status.Value); - } - - if (isActive.HasValue) - { - announcementQuery = isActive.Value - ? announcementQuery.Where(x => x.Status == AnnouncementStatus.Published) - : announcementQuery.Where(x => x.Status != AnnouncementStatus.Published); - } - - if (effectiveAt.HasValue) - { - var at = effectiveAt.Value; - announcementQuery = announcementQuery.Where(x => x.EffectiveFrom <= at && (x.EffectiveTo == null || x.EffectiveTo >= at)); - } - - var readQuery = context.TenantAnnouncementReads.AsNoTracking() - .Where(x => x.TenantId == tenantId); - - readQuery = userId.HasValue - ? readQuery.Where(x => x.UserId == null || x.UserId == userId.Value) - : readQuery.Where(x => x.UserId == null); - - var query = from announcement in announcementQuery - join read in readQuery on announcement.Id equals read.AnnouncementId into readGroup - where !readGroup.Any() - select announcement; - - return await query.ToListAsync(cancellationToken); - } - - /// - public Task FindByIdAsync(long tenantId, long announcementId, CancellationToken cancellationToken = default) - { - return context.TenantAnnouncements.AsNoTracking() - .FirstOrDefaultAsync(x => x.TenantId == tenantId && x.Id == announcementId, cancellationToken); - } - - /// - public Task AddAsync(TenantAnnouncement announcement, CancellationToken cancellationToken = default) - { - return context.TenantAnnouncements.AddAsync(announcement, cancellationToken).AsTask(); - } - - /// - public Task UpdateAsync(TenantAnnouncement announcement, CancellationToken cancellationToken = default) - { - context.TenantAnnouncements.Update(announcement); - return Task.CompletedTask; - } - - /// - public async Task DeleteAsync(long tenantId, long announcementId, CancellationToken cancellationToken = default) - { - var entity = await context.TenantAnnouncements.FirstOrDefaultAsync(x => x.TenantId == tenantId && x.Id == announcementId, cancellationToken); - if (entity != null) - { - context.TenantAnnouncements.Remove(entity); - } - } - - /// - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - { - return context.SaveChangesAsync(cancellationToken); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantNotificationRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantNotificationRepository.cs deleted file mode 100644 index 8738d6e..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantNotificationRepository.cs +++ /dev/null @@ -1,94 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Infrastructure.App.Persistence; - -namespace TakeoutSaaS.Infrastructure.App.Repositories; - -/// -/// EF 租户通知仓储。 -/// -public sealed class EfTenantNotificationRepository(TakeoutAppDbContext context) : ITenantNotificationRepository -{ - /// - public Task> SearchAsync( - long tenantId, - TenantNotificationSeverity? severity, - bool? unreadOnly, - DateTime? from, - DateTime? to, - CancellationToken cancellationToken = default) - { - var query = context.TenantNotifications.AsNoTracking() - .Where(x => x.TenantId == tenantId); - - if (severity.HasValue) - { - query = query.Where(x => x.Severity == severity.Value); - } - - if (unreadOnly == true) - { - query = query.Where(x => x.ReadAt == null); - } - - if (from.HasValue) - { - query = query.Where(x => x.SentAt >= from.Value); - } - - if (to.HasValue) - { - query = query.Where(x => x.SentAt <= to.Value); - } - - return query - .OrderByDescending(x => x.SentAt) - .ToListAsync(cancellationToken) - .ContinueWith(t => (IReadOnlyList)t.Result, cancellationToken); - } - - /// - public Task FindByIdAsync(long tenantId, long notificationId, CancellationToken cancellationToken = default) - { - return context.TenantNotifications - .FirstOrDefaultAsync(x => x.TenantId == tenantId && x.Id == notificationId, cancellationToken); - } - - /// - public Task ExistsByMetadataAsync( - long tenantId, - string title, - string metadataJson, - DateTime sentAfter, - CancellationToken cancellationToken = default) - { - return context.TenantNotifications.AsNoTracking() - .AnyAsync( - x => x.TenantId == tenantId - && x.Title == title - && x.MetadataJson == metadataJson - && x.SentAt >= sentAfter, - cancellationToken); - } - - /// - public Task AddAsync(TenantNotification notification, CancellationToken cancellationToken = default) - { - return context.TenantNotifications.AddAsync(notification, cancellationToken).AsTask(); - } - - /// - public Task UpdateAsync(TenantNotification notification, CancellationToken cancellationToken = default) - { - context.TenantNotifications.Update(notification); - return Task.CompletedTask; - } - - /// - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - { - return context.SaveChangesAsync(cancellationToken); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantPackageRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantPackageRepository.cs deleted file mode 100644 index ad9e266..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantPackageRepository.cs +++ /dev/null @@ -1,89 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Infrastructure.App.Persistence; - -namespace TakeoutSaaS.Infrastructure.App.Repositories; - -/// -/// 租户套餐仓储实现。 -/// -public sealed class EfTenantPackageRepository(TakeoutAppDbContext context) : ITenantPackageRepository -{ - /// - public Task FindByIdAsync(long id, CancellationToken cancellationToken = default) - { - return context.TenantPackages.AsNoTracking().FirstOrDefaultAsync(x => x.Id == id, cancellationToken); - } - - /// - public async Task> SearchAsync(string? keyword, bool? isActive, CancellationToken cancellationToken = default) - { - // 1. 构建基础查询 - var query = context.TenantPackages.AsNoTracking(); - - // 2. 关键字过滤 - if (!string.IsNullOrWhiteSpace(keyword)) - { - var normalized = keyword.Trim(); - query = query.Where(x => EF.Functions.ILike(x.Name, $"%{normalized}%") || EF.Functions.ILike(x.Description ?? string.Empty, $"%{normalized}%")); - } - - // 3. 状态过滤 - if (isActive.HasValue) - { - query = query.Where(x => x.IsActive == isActive.Value); - } - - // 4. 排序返回 - return await query - .OrderBy(x => x.SortOrder) - .ThenByDescending(x => x.CreatedAt) - .ToListAsync(cancellationToken); - } - - /// - public async Task> SearchPublicPurchasableAsync(CancellationToken cancellationToken = default) - { - // 1. 公共可选购套餐仅返回:已发布 + 对外可见 + 允许新购 + 启用 - return await context.TenantPackages.AsNoTracking() - .Where(x => - x.IsActive - && x.PublishStatus == TenantPackagePublishStatus.Published - && x.IsPublicVisible - && x.IsAllowNewTenantPurchase) - .OrderBy(x => x.SortOrder) - .ThenByDescending(x => x.CreatedAt) - .ToListAsync(cancellationToken); - } - - /// - public Task AddAsync(TenantPackage package, CancellationToken cancellationToken = default) - { - return context.TenantPackages.AddAsync(package, cancellationToken).AsTask(); - } - - /// - public Task UpdateAsync(TenantPackage package, CancellationToken cancellationToken = default) - { - context.TenantPackages.Update(package); - return Task.CompletedTask; - } - - /// - public async Task DeleteAsync(long id, CancellationToken cancellationToken = default) - { - var entity = await context.TenantPackages.FirstOrDefaultAsync(x => x.Id == id, cancellationToken); - if (entity != null) - { - context.TenantPackages.Remove(entity); - } - } - - /// - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - { - return context.SaveChangesAsync(cancellationToken); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantQuotaUsageHistoryRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantQuotaUsageHistoryRepository.cs deleted file mode 100644 index 701cbff..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantQuotaUsageHistoryRepository.cs +++ /dev/null @@ -1,24 +0,0 @@ -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Infrastructure.App.Persistence; - -namespace TakeoutSaaS.Infrastructure.App.Repositories; - -/// -/// 租户配额使用历史仓储实现。 -/// -public sealed class EfTenantQuotaUsageHistoryRepository(TakeoutAppDbContext context) : ITenantQuotaUsageHistoryRepository -{ - /// - public Task AddAsync(TenantQuotaUsageHistory history, CancellationToken cancellationToken = default) - { - return context.TenantQuotaUsageHistories.AddAsync(history, cancellationToken).AsTask(); - } - - /// - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - { - return context.SaveChangesAsync(cancellationToken); - } -} - diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantQuotaUsageRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantQuotaUsageRepository.cs deleted file mode 100644 index dd9c564..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantQuotaUsageRepository.cs +++ /dev/null @@ -1,50 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Infrastructure.App.Persistence; - -namespace TakeoutSaaS.Infrastructure.App.Repositories; - -/// -/// 租户配额使用仓储实现。 -/// -public sealed class EfTenantQuotaUsageRepository(TakeoutAppDbContext context) : ITenantQuotaUsageRepository -{ - /// - public Task FindAsync(long tenantId, TenantQuotaType quotaType, CancellationToken cancellationToken = default) - { - return context.TenantQuotaUsages - .FirstOrDefaultAsync(x => x.TenantId == tenantId && x.QuotaType == quotaType, cancellationToken); - } - - /// - public Task> GetByTenantAsync(long tenantId, CancellationToken cancellationToken = default) - { - return context.TenantQuotaUsages - .AsNoTracking() - .Where(x => x.TenantId == tenantId) - .OrderBy(x => x.QuotaType) - .ToListAsync(cancellationToken) - .ContinueWith(t => (IReadOnlyList)t.Result, cancellationToken); - } - - /// - public Task AddAsync(TenantQuotaUsage usage, CancellationToken cancellationToken = default) - { - return context.TenantQuotaUsages.AddAsync(usage, cancellationToken).AsTask(); - } - - /// - public Task UpdateAsync(TenantQuotaUsage usage, CancellationToken cancellationToken = default) - { - context.TenantQuotaUsages.Update(usage); - return Task.CompletedTask; - } - - /// - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - { - return context.SaveChangesAsync(cancellationToken); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantRepository.cs deleted file mode 100644 index cd56dff..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantRepository.cs +++ /dev/null @@ -1,356 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Infrastructure.App.Persistence; -using TakeoutSaaS.Infrastructure.Logs.Persistence; - -namespace TakeoutSaaS.Infrastructure.App.Repositories; - -/// -/// 租户聚合的 EF Core 仓储实现。 -/// -public sealed class EfTenantRepository(TakeoutAppDbContext context, TakeoutLogsDbContext logsContext) : ITenantRepository -{ - /// - public Task FindByIdAsync(long tenantId, CancellationToken cancellationToken = default) - { - return context.Tenants - .AsNoTracking() - .FirstOrDefaultAsync(x => x.Id == tenantId, cancellationToken); - } - - /// - public async Task> FindByIdsAsync(IReadOnlyCollection tenantIds, CancellationToken cancellationToken = default) - { - if (tenantIds.Count == 0) - { - return Array.Empty(); - } - - return await context.Tenants - .AsNoTracking() - .Where(x => tenantIds.Contains(x.Id)) - .ToListAsync(cancellationToken); - } - - /// - public async Task> SearchAsync( - TenantStatus? status, - string? keyword, - CancellationToken cancellationToken = default) - { - // 1. 构建基础查询 - var query = context.Tenants.AsNoTracking(); - - // 2. 按状态过滤 - if (status.HasValue) - { - query = query.Where(x => x.Status == status.Value); - } - - // 3. 按关键字过滤 - if (!string.IsNullOrWhiteSpace(keyword)) - { - keyword = keyword.Trim(); - query = query.Where(x => - EF.Functions.ILike(x.Name, $"%{keyword}%") || - EF.Functions.ILike(x.Code, $"%{keyword}%") || - EF.Functions.ILike(x.ContactName ?? string.Empty, $"%{keyword}%") || - EF.Functions.ILike(x.ContactPhone ?? string.Empty, $"%{keyword}%")); - } - - // 4. 排序返回 - return await query - .OrderByDescending(x => x.CreatedAt) - .ToListAsync(cancellationToken); - } - - /// - public async Task<(IReadOnlyList Items, int Total)> SearchPagedAsync( - TenantStatus? status, - TenantVerificationStatus? verificationStatus, - string? name, - string? contactName, - string? contactPhone, - string? keyword, - int page, - int pageSize, - CancellationToken cancellationToken = default) - { - var query = context.Tenants.AsNoTracking(); - - // 1. 按租户状态过滤 - if (status.HasValue) - { - query = query.Where(x => x.Status == status.Value); - } - - // 2. 按实名认证状态过滤(未提交视为 Draft) - if (verificationStatus.HasValue) - { - query = from tenant in query - join profile in context.TenantVerificationProfiles.AsNoTracking() - on tenant.Id equals profile.TenantId into profiles - from profile in profiles.DefaultIfEmpty() - where (profile == null ? TenantVerificationStatus.Draft : profile.Status) == verificationStatus.Value - select tenant; - } - - // 3. 按名称/联系人/电话过滤(模糊匹配) - if (!string.IsNullOrWhiteSpace(name)) - { - var normalizedName = name.Trim(); - query = query.Where(x => EF.Functions.ILike(x.Name, $"%{normalizedName}%")); - } - - // 4. 按联系人过滤(模糊匹配) - if (!string.IsNullOrWhiteSpace(contactName)) - { - var normalizedContactName = contactName.Trim(); - query = query.Where(x => EF.Functions.ILike(x.ContactName ?? string.Empty, $"%{normalizedContactName}%")); - } - - // 5. 按联系电话过滤(模糊匹配) - if (!string.IsNullOrWhiteSpace(contactPhone)) - { - var normalizedContactPhone = contactPhone.Trim(); - query = query.Where(x => EF.Functions.ILike(x.ContactPhone ?? string.Empty, $"%{normalizedContactPhone}%")); - } - - // 6. 兼容关键字查询:名称/编码/联系人/电话 - if (!string.IsNullOrWhiteSpace(keyword)) - { - var normalizedKeyword = keyword.Trim(); - query = query.Where(x => - EF.Functions.ILike(x.Name, $"%{normalizedKeyword}%") || - EF.Functions.ILike(x.Code, $"%{normalizedKeyword}%") || - EF.Functions.ILike(x.ContactName ?? string.Empty, $"%{normalizedKeyword}%") || - EF.Functions.ILike(x.ContactPhone ?? string.Empty, $"%{normalizedKeyword}%")); - } - - // 7. 先统计总数,再按创建时间倒序分页 - var total = await query.CountAsync(cancellationToken); - - // 8. 查询当前页数据 - var items = await query - .OrderByDescending(x => x.CreatedAt) - .Skip((page - 1) * pageSize) - .Take(pageSize) - .ToListAsync(cancellationToken); - - return (items, total); - } - - /// - public Task AddTenantAsync(Tenant tenant, CancellationToken cancellationToken = default) - { - return context.Tenants.AddAsync(tenant, cancellationToken).AsTask(); - } - - /// - public Task UpdateTenantAsync(Tenant tenant, CancellationToken cancellationToken = default) - { - context.Tenants.Update(tenant); - return Task.CompletedTask; - } - - /// - public Task ExistsByCodeAsync(string code, CancellationToken cancellationToken = default) - { - var normalized = code.Trim(); - return context.Tenants.AnyAsync(x => x.Code == normalized, cancellationToken); - } - - /// - public Task FindIdByCodeAsync(string code, CancellationToken cancellationToken = default) - { - // 1. 标准化编码 - var normalized = code.Trim(); - - // 2. 查询租户 ID(仅查询未删除且状态正常的租户) - return context.Tenants - .AsNoTracking() - .Where(x => x.Code == normalized && x.DeletedAt == null) - .Select(x => (long?)x.Id) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public Task ExistsByNameAsync(string name, long? excludeTenantId = null, CancellationToken cancellationToken = default) - { - // 1. 标准化名称 - var normalized = name.Trim(); - - // 2. 构建查询(名称使用 ILike 做不区分大小写的等值匹配) - var query = context.Tenants - .AsNoTracking() - .Where(x => EF.Functions.ILike(x.Name, normalized)); - - // 3. 更新场景排除自身 - if (excludeTenantId.HasValue) - { - query = query.Where(x => x.Id != excludeTenantId.Value); - } - - // 4. 判断是否存在 - return query.AnyAsync(cancellationToken); - } - - /// - public Task ExistsByContactPhoneAsync(string phone, CancellationToken cancellationToken = default) - { - var normalized = phone.Trim(); - return context.Tenants.AnyAsync(x => x.ContactPhone == normalized, cancellationToken); - } - - /// - public Task FindTenantIdByContactPhoneAsync(string phone, CancellationToken cancellationToken = default) - { - // 1. 标准化手机号 - var normalized = phone.Trim(); - // 2. 查询租户 ID - return context.Tenants.AsNoTracking() - .Where(x => x.ContactPhone == normalized) - .Select(x => (long?)x.Id) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public Task GetVerificationProfileAsync(long tenantId, CancellationToken cancellationToken = default) - { - return context.TenantVerificationProfiles - .AsNoTracking() - .FirstOrDefaultAsync(x => x.DeletedAt == null && x.TenantId == tenantId, cancellationToken); - } - - /// - public async Task> GetVerificationProfilesAsync( - IReadOnlyCollection tenantIds, - CancellationToken cancellationToken = default) - { - // 1. tenantIds 为空直接返回 - if (tenantIds.Count == 0) - { - return Array.Empty(); - } - - // 2. 批量查询实名资料 - return await context.TenantVerificationProfiles - .AsNoTracking() - .Where(x => x.DeletedAt == null && tenantIds.Contains(x.TenantId)) - .ToListAsync(cancellationToken); - } - - /// - public async Task UpsertVerificationProfileAsync(TenantVerificationProfile profile, CancellationToken cancellationToken = default) - { - // 1. 查询现有实名资料 - var existing = await context.TenantVerificationProfiles - .FirstOrDefaultAsync(x => x.DeletedAt == null && x.TenantId == profile.TenantId, cancellationToken); - - if (existing == null) - { - // 2. 不存在则新增 - await context.TenantVerificationProfiles.AddAsync(profile, cancellationToken); - return; - } - - // 3. 存在则更新当前值 - profile.Id = existing.Id; - context.Entry(existing).CurrentValues.SetValues(profile); - } - - /// - public Task GetActiveSubscriptionAsync(long tenantId, CancellationToken cancellationToken = default) - { - return context.TenantSubscriptions - .AsNoTracking() - .Where(x => x.DeletedAt == null && x.TenantId == tenantId) - .OrderByDescending(x => x.EffectiveTo) - .FirstOrDefaultAsync(cancellationToken); - } - - /// - public async Task> GetSubscriptionsAsync( - IReadOnlyCollection tenantIds, - CancellationToken cancellationToken = default) - { - // 1. tenantIds 为空直接返回 - if (tenantIds.Count == 0) - { - return Array.Empty(); - } - - // 2. 批量查询订阅数据 - return await context.TenantSubscriptions - .AsNoTracking() - .Where(x => x.DeletedAt == null && tenantIds.Contains(x.TenantId)) - .OrderByDescending(x => x.EffectiveTo) - .ToListAsync(cancellationToken); - } - - /// - public Task FindSubscriptionByIdAsync(long tenantId, long subscriptionId, CancellationToken cancellationToken = default) - { - return context.TenantSubscriptions - .FirstOrDefaultAsync( - x => x.DeletedAt == null && x.TenantId == tenantId && x.Id == subscriptionId, - cancellationToken); - } - - /// - public Task AddSubscriptionAsync(TenantSubscription subscription, CancellationToken cancellationToken = default) - { - return context.TenantSubscriptions.AddAsync(subscription, cancellationToken).AsTask(); - } - - /// - public Task UpdateSubscriptionAsync(TenantSubscription subscription, CancellationToken cancellationToken = default) - { - context.TenantSubscriptions.Update(subscription); - return Task.CompletedTask; - } - - /// - public Task AddSubscriptionHistoryAsync(TenantSubscriptionHistory history, CancellationToken cancellationToken = default) - { - return context.TenantSubscriptionHistories.AddAsync(history, cancellationToken).AsTask(); - } - - /// - public async Task> GetSubscriptionHistoryAsync(long tenantId, CancellationToken cancellationToken = default) - { - return await context.TenantSubscriptionHistories - .AsNoTracking() - .Where(x => x.DeletedAt == null && x.TenantId == tenantId) - .OrderByDescending(x => x.EffectiveFrom) - .ToListAsync(cancellationToken); - } - - /// - public Task AddAuditLogAsync(TenantAuditLog log, CancellationToken cancellationToken = default) - { - return logsContext.TenantAuditLogs.AddAsync(log, cancellationToken).AsTask(); - } - - /// - public async Task> GetAuditLogsAsync(long tenantId, CancellationToken cancellationToken = default) - { - return await logsContext.TenantAuditLogs - .AsNoTracking() - .Where(x => x.DeletedAt == null && x.TenantId == tenantId) - .OrderByDescending(x => x.CreatedAt) - .ToListAsync(cancellationToken); - } - - /// - public async Task SaveChangesAsync(CancellationToken cancellationToken = default) - { - // 1. 保存业务库变更 - await context.SaveChangesAsync(cancellationToken); - - // 2. 保存日志库变更 - await logsContext.SaveChangesAsync(cancellationToken); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Services/BillingDomainService.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Services/BillingDomainService.cs deleted file mode 100644 index 4fd3346..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Services/BillingDomainService.cs +++ /dev/null @@ -1,233 +0,0 @@ -using System.Globalization; -using System.Text.Json; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Domain.Tenants.Services; -using TakeoutSaaS.Shared.Abstractions.Ids; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Infrastructure.App.Services; - -/// -/// 账单领域服务实现。 -/// -public sealed class BillingDomainService( - ITenantBillingRepository billingRepository, - ITenantRepository tenantRepository, - ITenantContextAccessor tenantContextAccessor, - ITenantPackageRepository tenantPackageRepository, - IIdGenerator idGenerator) : IBillingDomainService -{ - /// - public async Task GenerateSubscriptionBillingAsync( - TenantSubscription subscription, - CancellationToken cancellationToken = default) - { - ArgumentNullException.ThrowIfNull(subscription); - - // 1. 校验幂等:同一周期开始时间只能存在一张未取消账单 - var exists = await billingRepository.ExistsNotCancelledByPeriodStartAsync( - subscription.TenantId, - subscription.EffectiveFrom, - cancellationToken); - if (exists) - { - throw new InvalidOperationException("该订阅周期的账单已存在。"); - } - - // 2. 查询套餐价格信息 - var package = await tenantPackageRepository.FindByIdAsync(subscription.TenantPackageId, cancellationToken); - if (package is null) - { - throw new InvalidOperationException("订阅未关联有效套餐,无法生成账单。"); - } - - // 3. 选择价格(简化规则:优先按年/按月) - var days = (subscription.EffectiveTo - subscription.EffectiveFrom).TotalDays; - var amountDue = days >= 300 ? package.YearlyPrice : package.MonthlyPrice; - if (!amountDue.HasValue) - { - throw new InvalidOperationException("套餐价格未配置,无法生成账单。"); - } - - // 4. 生成账单明细 - var lineItems = new List - { - BillingLineItem.Create( - itemType: "Subscription", - description: $"套餐 {package.Name} 订阅费用", - quantity: 1, - unitPrice: amountDue.Value) - }; - - // 5. 构建账单实体 - var now = DateTime.UtcNow; - return new TenantBillingStatement - { - Id = idGenerator.NextId(), - TenantId = subscription.TenantId, - StatementNo = GenerateStatementNo(), - BillingType = BillingType.Subscription, - SubscriptionId = subscription.Id, - PeriodStart = subscription.EffectiveFrom, - PeriodEnd = subscription.EffectiveTo, - AmountDue = amountDue.Value, - DiscountAmount = 0m, - TaxAmount = 0m, - AmountPaid = 0m, - Currency = "CNY", - Status = TenantBillingStatus.Pending, - DueDate = now.AddDays(7), - LineItemsJson = JsonSerializer.Serialize(lineItems), - Notes = subscription.Notes - }; - } - - /// - public Task GenerateQuotaPurchaseBillingAsync( - long tenantId, - QuotaPackage quotaPackage, - int quantity, - CancellationToken cancellationToken = default) - { - ArgumentNullException.ThrowIfNull(quotaPackage); - - if (quantity <= 0) - { - throw new ArgumentOutOfRangeException(nameof(quantity), "购买数量必须大于 0。"); - } - - // 1. 计算金额 - var amountDue = quotaPackage.Price * quantity; - - // 2. 生成账单明细 - var lineItems = new List - { - BillingLineItem.Create( - itemType: "QuotaPurchase", - description: $"配额包 {quotaPackage.Name} × {quantity}", - quantity: quantity, - unitPrice: quotaPackage.Price) - }; - - // 3. 构建账单实体 - var now = DateTime.UtcNow; - var billing = new TenantBillingStatement - { - Id = idGenerator.NextId(), - TenantId = tenantId, - StatementNo = GenerateStatementNo(), - BillingType = BillingType.QuotaPurchase, - SubscriptionId = null, - PeriodStart = now, - PeriodEnd = now, - AmountDue = amountDue, - DiscountAmount = 0m, - TaxAmount = 0m, - AmountPaid = 0m, - Currency = "CNY", - Status = TenantBillingStatus.Pending, - DueDate = now.AddDays(7), - LineItemsJson = JsonSerializer.Serialize(lineItems), - Notes = quotaPackage.Description - }; - - return Task.FromResult(billing); - } - - /// - public string GenerateStatementNo() - { - // 1. 账单号格式:BILL-{yyyyMMdd}-{序号} - var date = DateTime.UtcNow.ToString("yyyyMMdd", CultureInfo.InvariantCulture); - - // 2. 使用雪花 ID 作为全局递增序号,确保分布式唯一 - var sequence = idGenerator.NextId(); - return $"BILL-{date}-{sequence}"; - } - - /// - public async Task ProcessOverdueBillingsAsync(CancellationToken cancellationToken = default) - { - var processedAt = DateTime.UtcNow; - var currentTenantId = tenantContextAccessor.Current?.TenantId ?? 0; - if (currentTenantId != 0) - { - return await ProcessOverdueBillingsSingleTenantAsync(processedAt, cancellationToken); - } - - // 1. (空行后) 系统上下文:逐租户处理,避免跨租户写入 - var tenants = await tenantRepository.SearchAsync(null, null, cancellationToken); - var targets = tenants.Where(x => x.Id > 0).ToList(); - if (targets.Count == 0) - { - return 0; - } - - var totalUpdated = 0; - foreach (var tenant in targets) - { - using (tenantContextAccessor.EnterTenantScope(tenant.Id, "billing:overdue", tenant.Code)) - { - totalUpdated += await ProcessOverdueBillingsSingleTenantAsync(processedAt, cancellationToken); - } - } - - return totalUpdated; - } - - private async Task ProcessOverdueBillingsSingleTenantAsync(DateTime processedAt, CancellationToken cancellationToken) - { - // 1. 查询当前租户已超过到期日且仍处于待支付的账单(由仓储按 DueDate + Status 筛选) - var overdueBillings = await billingRepository.GetOverdueBillingsAsync(cancellationToken); - if (overdueBillings.Count == 0) - { - return 0; - } - - // 2. (空行后) 批量标记逾期(防御性:再次判断 Pending) - var updated = 0; - foreach (var billing in overdueBillings) - { - if (billing.Status != TenantBillingStatus.Pending) - { - continue; - } - - billing.MarkAsOverdue(); - billing.OverdueNotifiedAt ??= processedAt; - billing.UpdatedAt = processedAt; - - await billingRepository.UpdateAsync(billing, cancellationToken); - updated++; - } - - // 3. (空行后) 持久化 - if (updated > 0) - { - await billingRepository.SaveChangesAsync(cancellationToken); - } - - return updated; - } - - /// - public decimal CalculateTotalAmount(decimal baseAmount, decimal discountAmount, decimal taxAmount) - { - return baseAmount - discountAmount + taxAmount; - } - - /// - public bool CanProcessPayment(TenantBillingStatement billing) - { - ArgumentNullException.ThrowIfNull(billing); - - return billing.Status switch - { - TenantBillingStatus.Pending => true, - TenantBillingStatus.Overdue => true, - _ => false - }; - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Services/BillingExportService.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Services/BillingExportService.cs deleted file mode 100644 index 0fb69e2..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Services/BillingExportService.cs +++ /dev/null @@ -1,203 +0,0 @@ -using ClosedXML.Excel; -using CsvHelper; -using CsvHelper.Configuration; -using QuestPDF.Fluent; -using QuestPDF.Helpers; -using QuestPDF.Infrastructure; -using System.Globalization; -using System.Text; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Services; - -namespace TakeoutSaaS.Infrastructure.App.Services; - -/// -/// 账单导出服务实现(Excel/PDF/CSV)。 -/// -public sealed class BillingExportService : IBillingExportService -{ - /// - /// 初始化导出服务并配置 QuestPDF 许可证。 - /// - public BillingExportService() - { - QuestPDF.Settings.License = LicenseType.Community; - } - - /// - public Task ExportToExcelAsync(IReadOnlyList billings, CancellationToken cancellationToken = default) - { - ArgumentNullException.ThrowIfNull(billings); - - // 1. 创建工作簿与工作表 - using var workbook = new XLWorkbook(); - var worksheet = workbook.Worksheets.Add("Billings"); - - // 2. 写入表头 - var headers = new[] - { - "Id", "TenantId", "StatementNo", "BillingType", "Status", - "PeriodStart", "PeriodEnd", "AmountDue", "DiscountAmount", "TaxAmount", "TotalAmount", - "AmountPaid", "Currency", "DueDate", "Notes", "LineItemsJson" - }; - - for (var i = 0; i < headers.Length; i++) - { - worksheet.Cell(1, i + 1).Value = headers[i]; - } - - // 3. 写入数据行 - for (var rowIndex = 0; rowIndex < billings.Count; rowIndex++) - { - cancellationToken.ThrowIfCancellationRequested(); - - var billing = billings[rowIndex]; - var totalAmount = billing.CalculateTotalAmount(); - var r = rowIndex + 2; - - worksheet.Cell(r, 1).Value = billing.Id; - worksheet.Cell(r, 2).Value = billing.TenantId; - worksheet.Cell(r, 3).Value = billing.StatementNo; - worksheet.Cell(r, 4).Value = billing.BillingType.ToString(); - worksheet.Cell(r, 5).Value = billing.Status.ToString(); - worksheet.Cell(r, 6).Value = billing.PeriodStart.ToString("O", CultureInfo.InvariantCulture); - worksheet.Cell(r, 7).Value = billing.PeriodEnd.ToString("O", CultureInfo.InvariantCulture); - worksheet.Cell(r, 8).Value = billing.AmountDue; - worksheet.Cell(r, 9).Value = billing.DiscountAmount; - worksheet.Cell(r, 10).Value = billing.TaxAmount; - worksheet.Cell(r, 11).Value = totalAmount; - worksheet.Cell(r, 12).Value = billing.AmountPaid; - worksheet.Cell(r, 13).Value = billing.Currency; - worksheet.Cell(r, 14).Value = billing.DueDate.ToString("O", CultureInfo.InvariantCulture); - worksheet.Cell(r, 15).Value = billing.Notes ?? string.Empty; - worksheet.Cell(r, 16).Value = billing.LineItemsJson ?? string.Empty; - } - - // 4. 自动调整列宽并输出 - worksheet.Columns().AdjustToContents(); - - using var stream = new MemoryStream(); - workbook.SaveAs(stream); - return Task.FromResult(stream.ToArray()); - } - - /// - public Task ExportToPdfAsync(IReadOnlyList billings, CancellationToken cancellationToken = default) - { - ArgumentNullException.ThrowIfNull(billings); - - // 1. 生成 PDF 文档(避免复杂表格,按条目输出) - var document = Document.Create(container => - { - container.Page(page => - { - page.Size(PageSizes.A4); - page.Margin(20); - page.DefaultTextStyle(x => x.FontSize(10)); - - page.Content().Column(column => - { - column.Spacing(6); - - // 2. 标题 - column.Item().Text("Billings Export").FontSize(16).SemiBold(); - - // 3. 逐条输出 - for (var i = 0; i < billings.Count; i++) - { - cancellationToken.ThrowIfCancellationRequested(); - - var b = billings[i]; - var total = b.CalculateTotalAmount(); - - column.Item().Border(1).BorderColor(Colors.Grey.Lighten2).Padding(8).Column(item => - { - item.Spacing(2); - item.Item().Text($"StatementNo: {b.StatementNo}"); - item.Item().Text($"TenantId: {b.TenantId} BillingType: {b.BillingType} Status: {b.Status}"); - item.Item().Text($"Period: {b.PeriodStart:yyyy-MM-dd} ~ {b.PeriodEnd:yyyy-MM-dd} DueDate: {b.DueDate:yyyy-MM-dd}"); - item.Item().Text($"AmountDue: {b.AmountDue:0.##} Discount: {b.DiscountAmount:0.##} Tax: {b.TaxAmount:0.##}"); - item.Item().Text($"Total: {total:0.##} Paid: {b.AmountPaid:0.##} Currency: {b.Currency}"); - - if (!string.IsNullOrWhiteSpace(b.Notes)) - { - item.Item().Text($"Notes: {b.Notes}"); - } - }); - } - }); - }); - }); - - // 4. 输出字节 - var bytes = document.GeneratePdf(); - return Task.FromResult(bytes); - } - - /// - public async Task ExportToCsvAsync(IReadOnlyList billings, CancellationToken cancellationToken = default) - { - ArgumentNullException.ThrowIfNull(billings); - - // 1. 使用 UTF-8 BOM,便于 Excel 直接打开 - await using var stream = new MemoryStream(); - await using var writer = new StreamWriter(stream, new UTF8Encoding(encoderShouldEmitUTF8Identifier: true), leaveOpen: true); - - var config = new CsvConfiguration(CultureInfo.InvariantCulture) - { - HasHeaderRecord = true - }; - - await using var csv = new CsvWriter(writer, config); - - // 2. 写入表头 - csv.WriteField("Id"); - csv.WriteField("TenantId"); - csv.WriteField("StatementNo"); - csv.WriteField("BillingType"); - csv.WriteField("Status"); - csv.WriteField("PeriodStart"); - csv.WriteField("PeriodEnd"); - csv.WriteField("AmountDue"); - csv.WriteField("DiscountAmount"); - csv.WriteField("TaxAmount"); - csv.WriteField("TotalAmount"); - csv.WriteField("AmountPaid"); - csv.WriteField("Currency"); - csv.WriteField("DueDate"); - csv.WriteField("Notes"); - csv.WriteField("LineItemsJson"); - await csv.NextRecordAsync(); - - // 3. 写入数据行 - foreach (var b in billings) - { - cancellationToken.ThrowIfCancellationRequested(); - - var total = b.CalculateTotalAmount(); - - csv.WriteField(b.Id); - csv.WriteField(b.TenantId); - csv.WriteField(b.StatementNo); - csv.WriteField(b.BillingType.ToString()); - csv.WriteField(b.Status.ToString()); - csv.WriteField(b.PeriodStart.ToString("O", CultureInfo.InvariantCulture)); - csv.WriteField(b.PeriodEnd.ToString("O", CultureInfo.InvariantCulture)); - csv.WriteField(b.AmountDue); - csv.WriteField(b.DiscountAmount); - csv.WriteField(b.TaxAmount); - csv.WriteField(total); - csv.WriteField(b.AmountPaid); - csv.WriteField(b.Currency); - csv.WriteField(b.DueDate.ToString("O", CultureInfo.InvariantCulture)); - csv.WriteField(b.Notes ?? string.Empty); - csv.WriteField(b.LineItemsJson ?? string.Empty); - - await csv.NextRecordAsync(); - } - - // 4. Flush 并返回字节 - await writer.FlushAsync(cancellationToken); - return stream.ToArray(); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Services/DeliveryZoneService.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Services/DeliveryZoneService.cs deleted file mode 100644 index 4bb6c84..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Services/DeliveryZoneService.cs +++ /dev/null @@ -1,375 +0,0 @@ -using System.Globalization; -using System.Linq; -using System.Text.Json; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Application.App.Stores.Services; -using TakeoutSaaS.Domain.Stores.Entities; - -namespace TakeoutSaaS.Infrastructure.App.Services; - -/// -/// 配送范围检测服务实现。 -/// -public sealed class DeliveryZoneService : IDeliveryZoneService -{ - private const double CoordinateTolerance = 1e-6; - - /// - public StoreDeliveryCheckResultDto CheckPointInZones( - IReadOnlyList zones, - double longitude, - double latitude) - { - // 1. 无配送区域直接返回 - if (zones is null || zones.Count == 0) - { - return new StoreDeliveryCheckResultDto { InRange = false }; - } - // 2. (空行后) 逐个检测多边形命中 - foreach (var zone in zones) - { - if (!TryReadPolygons(zone.PolygonGeoJson, out var polygons)) - { - continue; - } - foreach (var polygon in polygons) - { - if (!IsPointInPolygon(polygon, longitude, latitude)) - { - continue; - } - return new StoreDeliveryCheckResultDto - { - InRange = true, - DeliveryZoneId = zone.Id, - DeliveryZoneName = zone.ZoneName - }; - } - } - // 3. (空行后) 未命中任何区域 - return new StoreDeliveryCheckResultDto { InRange = false }; - } - - private static bool TryReadPolygons(string geoJson, out List polygons) - { - polygons = []; - if (string.IsNullOrWhiteSpace(geoJson)) - { - return false; - } - try - { - using var document = JsonDocument.Parse(geoJson); - if (!TryReadPolygons(document.RootElement, polygons)) - { - return false; - } - return polygons.Count > 0; - } - catch (JsonException) - { - return false; - } - } - - private static bool TryReadPolygons(JsonElement root, ICollection polygons) - { - if (root.ValueKind == JsonValueKind.String) - { - var inner = root.GetString(); - if (string.IsNullOrWhiteSpace(inner)) - { - return false; - } - using var innerDocument = JsonDocument.Parse(inner); - return TryReadPolygons(innerDocument.RootElement, polygons); - } - - if (root.ValueKind != JsonValueKind.Object) - { - return false; - } - - if (!TryGetPropertyIgnoreCase(root, "type", out var typeElement) - || typeElement.ValueKind != JsonValueKind.String) - { - return false; - } - - var type = typeElement.GetString(); - if (string.Equals(type, "FeatureCollection", StringComparison.OrdinalIgnoreCase)) - { - if (!TryGetPropertyIgnoreCase(root, "features", out var featuresElement) - || featuresElement.ValueKind != JsonValueKind.Array) - { - return false; - } - - foreach (var featureElement in featuresElement.EnumerateArray()) - { - if (featureElement.ValueKind != JsonValueKind.Object) - { - continue; - } - if (!TryGetPropertyIgnoreCase(featureElement, "geometry", out var geometryElement)) - { - continue; - } - TryReadPolygons(geometryElement, polygons); - } - return polygons.Count > 0; - } - - if (string.Equals(type, "Feature", StringComparison.OrdinalIgnoreCase)) - { - if (!TryGetPropertyIgnoreCase(root, "geometry", out var geometryElement)) - { - return false; - } - return TryReadPolygons(geometryElement, polygons); - } - - if (string.Equals(type, "Polygon", StringComparison.OrdinalIgnoreCase)) - { - if (!TryGetPropertyIgnoreCase(root, "coordinates", out var coordinatesElement)) - { - return false; - } - if (!TryReadPolygonFromCoordinates(coordinatesElement, out var polygon)) - { - return false; - } - polygons.Add(polygon); - return true; - } - - if (string.Equals(type, "MultiPolygon", StringComparison.OrdinalIgnoreCase)) - { - if (!TryGetPropertyIgnoreCase(root, "coordinates", out var coordinatesElement) - || coordinatesElement.ValueKind != JsonValueKind.Array) - { - return false; - } - - foreach (var polygonElement in coordinatesElement.EnumerateArray()) - { - if (!TryReadPolygonFromCoordinates(polygonElement, out var polygon)) - { - continue; - } - polygons.Add(polygon); - } - return polygons.Count > 0; - } - - return false; - } - - private static bool TryReadPolygonFromCoordinates(JsonElement coordinatesElement, out Polygon polygon) - { - polygon = default!; - if (!TryReadRings(coordinatesElement, out var rings) || rings.Count == 0) - { - return false; - } - var outer = rings[0]; - if (outer.Count < 3) - { - return false; - } - var holes = rings.Count > 1 ? rings.Skip(1).ToList() : []; - polygon = new Polygon(outer, holes); - return true; - } - - private static bool TryReadRings(JsonElement element, out List> rings) - { - rings = []; - if (element.ValueKind != JsonValueKind.Array || element.GetArrayLength() == 0) - { - return false; - } - - if (IsPositionArray(element[0])) - { - if (!TryReadRing(element, out var ring)) - { - return false; - } - rings.Add(ring); - return true; - } - - foreach (var ringElement in element.EnumerateArray()) - { - if (!TryReadRing(ringElement, out var ring)) - { - return false; - } - rings.Add(ring); - } - - return rings.Count > 0; - } - - private static bool TryReadRing(JsonElement ringElement, out List ring) - { - ring = []; - if (ringElement.ValueKind != JsonValueKind.Array) - { - return false; - } - - foreach (var pointElement in ringElement.EnumerateArray()) - { - if (!TryReadPosition(pointElement, out var point)) - { - return false; - } - ring.Add(point); - } - - if (ring.Count >= 2 && AreSamePoint(ring[0], ring[^1])) - { - ring.RemoveAt(ring.Count - 1); - } - - return ring.Count >= 3; - } - - private static bool TryReadPosition(JsonElement pointElement, out Point point) - { - point = default; - if (pointElement.ValueKind != JsonValueKind.Array || pointElement.GetArrayLength() < 2) - { - return false; - } - - if (!TryGetCoordinate(pointElement[0], out var longitude) - || !TryGetCoordinate(pointElement[1], out var latitude)) - { - return false; - } - - point = new Point(longitude, latitude); - return true; - } - - private static bool TryGetCoordinate(JsonElement element, out double value) - { - value = 0; - if (element.ValueKind == JsonValueKind.Number) - { - return element.TryGetDouble(out value); - } - if (element.ValueKind == JsonValueKind.String) - { - return double.TryParse(element.GetString(), NumberStyles.Float, CultureInfo.InvariantCulture, out value); - } - return false; - } - - private static bool IsPositionArray(JsonElement element) - => element.ValueKind == JsonValueKind.Array - && element.GetArrayLength() >= 2 - && TryGetCoordinate(element[0], out _) - && TryGetCoordinate(element[1], out _); - - private static bool TryGetPropertyIgnoreCase(JsonElement element, string propertyName, out JsonElement value) - { - if (element.TryGetProperty(propertyName, out value)) - { - return true; - } - - foreach (var property in element.EnumerateObject()) - { - if (string.Equals(property.Name, propertyName, StringComparison.OrdinalIgnoreCase)) - { - value = property.Value; - return true; - } - } - - value = default; - return false; - } - - private static bool IsPointInPolygon(Polygon polygon, double x, double y) - { - if (!IsPointInRing(polygon.Outer, x, y)) - { - return false; - } - - foreach (var hole in polygon.Holes) - { - if (IsPointInRing(hole, x, y)) - { - return false; - } - } - - return true; - } - - private static bool IsPointInRing(IReadOnlyList ring, double x, double y) - { - if (IsPointOnBoundary(ring, x, y)) - { - return true; - } - - var inside = false; - for (var i = 0; i < ring.Count; i++) - { - var j = i == 0 ? ring.Count - 1 : i - 1; - var xi = ring[i].Longitude; - var yi = ring[i].Latitude; - var xj = ring[j].Longitude; - var yj = ring[j].Latitude; - var intersects = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi + double.Epsilon) + xi); - if (intersects) - { - inside = !inside; - } - } - - return inside; - } - - private static bool IsPointOnBoundary(IReadOnlyList ring, double x, double y) - { - for (var i = 0; i < ring.Count; i++) - { - var j = i == ring.Count - 1 ? 0 : i + 1; - if (IsPointOnSegment(ring[i], ring[j], x, y)) - { - return true; - } - } - return false; - } - - private static bool IsPointOnSegment(Point start, Point end, double x, double y) - { - var cross = (end.Longitude - start.Longitude) * (y - start.Latitude) - - (end.Latitude - start.Latitude) * (x - start.Longitude); - if (Math.Abs(cross) > CoordinateTolerance) - { - return false; - } - - var dot = (x - start.Longitude) * (x - end.Longitude) - + (y - start.Latitude) * (y - end.Latitude); - return dot <= CoordinateTolerance; - } - - private static bool AreSamePoint(Point first, Point second) - => Math.Abs(first.Longitude - second.Longitude) <= CoordinateTolerance - && Math.Abs(first.Latitude - second.Latitude) <= CoordinateTolerance; - - private readonly record struct Point(double Longitude, double Latitude); - - private sealed record Polygon(IReadOnlyList Outer, IReadOnlyList> Holes); -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Services/GeoJsonValidationService.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Services/GeoJsonValidationService.cs deleted file mode 100644 index 272acb3..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Services/GeoJsonValidationService.cs +++ /dev/null @@ -1,221 +0,0 @@ -using System.Text.Json; -using TakeoutSaaS.Application.App.Stores.Services; - -namespace TakeoutSaaS.Infrastructure.App.Services; - -/// -/// GeoJSON 校验服务实现。 -/// -public sealed class GeoJsonValidationService : IGeoJsonValidationService -{ - private const double CoordinateTolerance = 1e-6; - - /// - public GeoJsonValidationResult ValidatePolygon(string geoJson) - { - // 1. 基础校验 - if (string.IsNullOrWhiteSpace(geoJson)) - { - return BuildInvalid("GeoJSON 不能为空"); - } - // 2. (空行后) 解析与验证结构 - try - { - using var document = JsonDocument.Parse(geoJson); - var root = document.RootElement; - if (root.ValueKind != JsonValueKind.Object) - { - return BuildInvalid("GeoJSON 格式错误"); - } - if (!root.TryGetProperty("type", out var typeElement) || typeElement.ValueKind != JsonValueKind.String) - { - return BuildInvalid("GeoJSON 缺少 type"); - } - var type = typeElement.GetString(); - if (!string.Equals(type, "Polygon", StringComparison.OrdinalIgnoreCase)) - { - return BuildInvalid("仅支持 Polygon 类型"); - } - if (!root.TryGetProperty("coordinates", out var coordinatesElement) || coordinatesElement.ValueKind != JsonValueKind.Array) - { - return BuildInvalid("GeoJSON 缺少 coordinates"); - } - if (coordinatesElement.GetArrayLength() == 0) - { - return BuildInvalid("GeoJSON coordinates 为空"); - } - var ringElement = coordinatesElement[0]; - if (ringElement.ValueKind != JsonValueKind.Array) - { - return BuildInvalid("GeoJSON 坐标格式错误"); - } - var points = new List(); - foreach (var pointElement in ringElement.EnumerateArray()) - { - if (pointElement.ValueKind != JsonValueKind.Array || pointElement.GetArrayLength() < 2) - { - return BuildInvalid("坐标点格式错误"); - } - if (!pointElement[0].TryGetDouble(out var longitude) || !pointElement[1].TryGetDouble(out var latitude)) - { - return BuildInvalid("坐标点必须为数值"); - } - points.Add(new Point(longitude, latitude)); - } - if (points.Count < 3) - { - return BuildInvalid("多边形至少需要 3 个点"); - } - var distinctCount = CountDistinct(points); - if (distinctCount < 3) - { - return BuildInvalid("多边形坐标点不足"); - } - var normalized = Normalize(points, out var normalizedJson); - if (normalized.Count < 4) - { - return BuildInvalid("多边形至少需要 4 个点(含闭合点)"); - } - if (HasSelfIntersection(normalized)) - { - return BuildInvalid("多边形存在自相交"); - } - return new GeoJsonValidationResult - { - IsValid = true, - NormalizedGeoJson = normalizedJson - }; - } - catch (JsonException) - { - return BuildInvalid("GeoJSON 解析失败"); - } - } - - private static GeoJsonValidationResult BuildInvalid(string message) => new() - { - IsValid = false, - ErrorMessage = message - }; - - private static int CountDistinct(IReadOnlyList points) - { - var distinct = new List(); - foreach (var point in points) - { - if (distinct.Any(existing => AreSamePoint(existing, point))) - { - continue; - } - distinct.Add(point); - } - return distinct.Count; - } - - private static List Normalize(IReadOnlyList points, out string? normalizedJson) - { - var normalized = new List(points); - if (!AreSamePoint(normalized[0], normalized[^1])) - { - normalized.Add(normalized[0]); - normalizedJson = BuildGeoJson(normalized); - return normalized; - } - normalizedJson = null; - return normalized; - } - - private static string BuildGeoJson(IReadOnlyList points) - { - var coordinates = points - .Select(point => new[] { point.Longitude, point.Latitude }) - .ToArray(); - var payload = new Dictionary - { - { "type", "Polygon" }, - { "coordinates", new[] { coordinates } } - }; - return JsonSerializer.Serialize(payload); - } - - private static bool HasSelfIntersection(IReadOnlyList points) - { - var segmentCount = points.Count - 1; - for (var i = 0; i < segmentCount; i++) - { - var a1 = points[i]; - var a2 = points[i + 1]; - for (var j = i + 1; j < segmentCount; j++) - { - if (Math.Abs(i - j) <= 1) - { - continue; - } - if (i == 0 && j == segmentCount - 1) - { - continue; - } - var b1 = points[j]; - var b2 = points[j + 1]; - if (SegmentsIntersect(a1, a2, b1, b2)) - { - return true; - } - } - } - return false; - } - - private static bool SegmentsIntersect(Point p1, Point q1, Point p2, Point q2) - { - var o1 = Orientation(p1, q1, p2); - var o2 = Orientation(p1, q1, q2); - var o3 = Orientation(p2, q2, p1); - var o4 = Orientation(p2, q2, q1); - - if (o1 != o2 && o3 != o4) - { - return true; - } - if (o1 == 0 && OnSegment(p1, p2, q1)) - { - return true; - } - if (o2 == 0 && OnSegment(p1, q2, q1)) - { - return true; - } - if (o3 == 0 && OnSegment(p2, p1, q2)) - { - return true; - } - if (o4 == 0 && OnSegment(p2, q1, q2)) - { - return true; - } - return false; - } - - private static int Orientation(Point p, Point q, Point r) - { - var value = (q.Latitude - p.Latitude) * (r.Longitude - q.Longitude) - - (q.Longitude - p.Longitude) * (r.Latitude - q.Latitude); - if (Math.Abs(value) <= CoordinateTolerance) - { - return 0; - } - return value > 0 ? 1 : 2; - } - - private static bool OnSegment(Point p, Point q, Point r) - => q.Longitude <= Math.Max(p.Longitude, r.Longitude) + CoordinateTolerance - && q.Longitude >= Math.Min(p.Longitude, r.Longitude) - CoordinateTolerance - && q.Latitude <= Math.Max(p.Latitude, r.Latitude) + CoordinateTolerance - && q.Latitude >= Math.Min(p.Latitude, r.Latitude) - CoordinateTolerance; - - private static bool AreSamePoint(Point first, Point second) - => Math.Abs(first.Longitude - second.Longitude) <= CoordinateTolerance - && Math.Abs(first.Latitude - second.Latitude) <= CoordinateTolerance; - - private readonly record struct Point(double Longitude, double Latitude); -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Services/MerchantExportService.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Services/MerchantExportService.cs deleted file mode 100644 index dd56293..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Services/MerchantExportService.cs +++ /dev/null @@ -1,152 +0,0 @@ -using QuestPDF.Fluent; -using QuestPDF.Helpers; -using QuestPDF.Infrastructure; -using System.Globalization; -using TakeoutSaaS.Domain.Common.Enums; -using TakeoutSaaS.Domain.Merchants.Entities; -using TakeoutSaaS.Domain.Merchants.Enums; -using TakeoutSaaS.Domain.Merchants.Services; -using TakeoutSaaS.Domain.Stores.Entities; -using TakeoutSaaS.Domain.Stores.Enums; - -namespace TakeoutSaaS.Infrastructure.App.Services; - -/// -/// 商户导出服务实现(PDF)。 -/// -public sealed class MerchantExportService : IMerchantExportService -{ - public MerchantExportService() - { - QuestPDF.Settings.License = LicenseType.Community; - } - - /// - public Task ExportToPdfAsync( - Merchant merchant, - string? tenantName, - IReadOnlyList stores, - IReadOnlyList auditLogs, - CancellationToken cancellationToken = default) - { - ArgumentNullException.ThrowIfNull(merchant); - - var safeStores = stores ?? Array.Empty(); - var safeAuditLogs = auditLogs ?? Array.Empty(); - - var document = Document.Create(container => - { - container.Page(page => - { - page.Size(PageSizes.A4); - page.Margin(24); - page.DefaultTextStyle(x => x.FontSize(10)); - - page.Content().Column(column => - { - column.Spacing(10); - column.Item().Text("Merchant Export").FontSize(16).SemiBold(); - - column.Item().Element(section => BuildBasicSection(section, merchant, tenantName)); - column.Item().Element(section => BuildStoresSection(section, safeStores, cancellationToken)); - column.Item().Element(section => BuildAuditSection(section, safeAuditLogs, cancellationToken)); - }); - }); - }); - - return Task.FromResult(document.GeneratePdf()); - } - - private static void BuildBasicSection(IContainer container, Merchant merchant, string? tenantName) - { - container.Border(1).BorderColor(Colors.Grey.Lighten2).Padding(10).Column(column => - { - column.Spacing(4); - column.Item().Text("Basic Information").SemiBold(); - column.Item().Text($"Merchant: {merchant.BrandName}"); - column.Item().Text($"Tenant: {tenantName ?? "-"} (ID: {merchant.TenantId})"); - column.Item().Text($"Operating Mode: {ResolveOperatingMode(merchant.OperatingMode)}"); - column.Item().Text($"Status: {merchant.Status}"); - column.Item().Text($"Frozen: {(merchant.IsFrozen ? "Yes" : "No")}"); - column.Item().Text($"License Number: {merchant.BusinessLicenseNumber ?? "-"}"); - column.Item().Text($"Legal Representative: {merchant.LegalPerson ?? "-"}"); - column.Item().Text($"Registered Address: {merchant.Address ?? "-"}"); - column.Item().Text($"Contact Phone: {merchant.ContactPhone}"); - column.Item().Text($"Contact Email: {merchant.ContactEmail ?? "-"}"); - column.Item().Text($"Approved At: {FormatDateTime(merchant.ApprovedAt)}"); - column.Item().Text($"Approved By: {merchant.ApprovedBy?.ToString() ?? "-"}"); - }); - } - - private static void BuildStoresSection(IContainer container, IReadOnlyList stores, CancellationToken cancellationToken) - { - container.Border(1).BorderColor(Colors.Grey.Lighten2).Padding(10).Column(column => - { - column.Spacing(4); - column.Item().Text("Stores").SemiBold(); - - if (stores.Count == 0) - { - column.Item().Text("No stores."); - return; - } - - for (var i = 0; i < stores.Count; i++) - { - cancellationToken.ThrowIfCancellationRequested(); - - var store = stores[i]; - column.Item().Text($"{i + 1}. {store.Name} | {ResolveStoreStatus(store.Status)} | {store.Address ?? "-"} | {store.Phone ?? "-"}"); - } - }); - } - - private static void BuildAuditSection(IContainer container, IReadOnlyList auditLogs, CancellationToken cancellationToken) - { - container.Border(1).BorderColor(Colors.Grey.Lighten2).Padding(10).Column(column => - { - column.Spacing(4); - column.Item().Text("Audit History").SemiBold(); - - if (auditLogs.Count == 0) - { - column.Item().Text("No audit records."); - return; - } - - for (var i = 0; i < auditLogs.Count; i++) - { - cancellationToken.ThrowIfCancellationRequested(); - - var log = auditLogs[i]; - var title = string.IsNullOrWhiteSpace(log.Title) ? log.Action.ToString() : log.Title; - column.Item().Text($"{i + 1}. {title} | {log.OperatorName ?? "-"} | {FormatDateTime(log.CreatedAt)}"); - if (!string.IsNullOrWhiteSpace(log.Description)) - { - column.Item().Text($" {log.Description}"); - } - } - }); - } - - private static string ResolveOperatingMode(OperatingMode? mode) - => mode switch - { - OperatingMode.SameEntity => "SameEntity", - OperatingMode.DifferentEntity => "DifferentEntity", - _ => "-" - }; - - private static string ResolveStoreStatus(StoreStatus status) - => status switch - { - StoreStatus.Closed => "Closed", - StoreStatus.Preparing => "Preparing", - StoreStatus.Operating => "Operating", - StoreStatus.Suspended => "Suspended", - _ => status.ToString() - }; - - private static string FormatDateTime(DateTime? value) - => value.HasValue ? value.Value.ToString("yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture) : "-"; -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Services/StoreFeeCalculationService.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Services/StoreFeeCalculationService.cs deleted file mode 100644 index 1873ef0..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Services/StoreFeeCalculationService.cs +++ /dev/null @@ -1,125 +0,0 @@ -using System.Globalization; -using TakeoutSaaS.Application.App.Stores; -using TakeoutSaaS.Application.App.Stores.Dto; -using TakeoutSaaS.Application.App.Stores.Services; -using TakeoutSaaS.Domain.Stores.Entities; -using TakeoutSaaS.Domain.Stores.Enums; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; - -namespace TakeoutSaaS.Infrastructure.App.Services; - -/// -/// 门店费用计算服务实现。 -/// -public sealed class StoreFeeCalculationService : IStoreFeeCalculationService -{ - /// - public StoreFeeCalculationResultDto Calculate(StoreFee fee, StoreFeeCalculationRequestDto request) - { - // 1. 计算起送费满足情况 - var minimum = fee.MinimumOrderAmount; - if (request.OrderAmount < minimum) - { - var shortfall = minimum - request.OrderAmount; - var message = $"还差{shortfall.ToString("0.##", CultureInfo.InvariantCulture)}元起送"; - return new StoreFeeCalculationResultDto - { - OrderAmount = request.OrderAmount, - MinimumOrderAmount = minimum, - MeetsMinimum = false, - Shortfall = shortfall, - DeliveryFee = 0m, - PackagingFee = 0m, - PackagingFeeMode = fee.PackagingFeeMode, - OrderPackagingFeeMode = fee.OrderPackagingFeeMode, - TotalFee = 0m, - TotalAmount = request.OrderAmount, - Message = message - }; - } - - // 2. (空行后) 计算配送费 - var deliveryFee = fee.BaseDeliveryFee; - if (fee.FreeDeliveryThreshold.HasValue && request.OrderAmount >= fee.FreeDeliveryThreshold.Value) - { - deliveryFee = 0m; - } - - // 3. (空行后) 计算打包费 - var packagingFee = 0m; - IReadOnlyList? breakdown = null; - if (fee.PackagingFeeMode == PackagingFeeMode.Fixed) - { - if (fee.OrderPackagingFeeMode == OrderPackagingFeeMode.Tiered) - { - var tiers = StoreFeeTierHelper.Deserialize(fee.PackagingFeeTiersJson); - if (tiers.Count == 0) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "阶梯打包费配置缺失"); - } - packagingFee = ResolveTieredFee(request.OrderAmount, tiers); - } - else - { - packagingFee = fee.FixedPackagingFee; - } - } - else - { - if (request.Items.Count == 0) - { - throw new BusinessException(ErrorCodes.ValidationFailed, "商品计费模式必须提供商品列表"); - } - var list = new List(request.Items.Count); - foreach (var item in request.Items) - { - var subtotal = item.PackagingFee * item.Quantity; - packagingFee += subtotal; - list.Add(new StoreFeeCalculationBreakdownDto - { - SkuId = item.SkuId, - Quantity = item.Quantity, - UnitFee = item.PackagingFee, - Subtotal = subtotal - }); - } - breakdown = list; - } - - // 4. (空行后) 汇总结果 - var totalFee = deliveryFee + packagingFee; - var totalAmount = request.OrderAmount + totalFee; - return new StoreFeeCalculationResultDto - { - OrderAmount = request.OrderAmount, - MinimumOrderAmount = minimum, - MeetsMinimum = true, - DeliveryFee = deliveryFee, - PackagingFee = packagingFee, - PackagingFeeMode = fee.PackagingFeeMode, - OrderPackagingFeeMode = fee.OrderPackagingFeeMode, - PackagingFeeBreakdown = breakdown, - TotalFee = totalFee, - TotalAmount = totalAmount - }; - } - - private static decimal ResolveTieredFee(decimal orderAmount, IReadOnlyList tiers) - { - foreach (var tier in tiers) - { - if (orderAmount < tier.MinPrice) - { - continue; - } - - if (!tier.MaxPrice.HasValue || orderAmount <= tier.MaxPrice.Value) - { - return tier.Fee; - } - } - - return tiers[^1].Fee; - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Services/StoreSchedulerService.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Services/StoreSchedulerService.cs deleted file mode 100644 index 621b02a..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Services/StoreSchedulerService.cs +++ /dev/null @@ -1,302 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Services; -using TakeoutSaaS.Domain.Stores.Entities; -using TakeoutSaaS.Domain.Stores.Enums; -using TakeoutSaaS.Infrastructure.App.Persistence; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Infrastructure.App.Services; - -/// -/// 门店定时任务服务实现。 -/// -public sealed class StoreSchedulerService( - TakeoutAppDbContext context, - ITenantContextAccessor tenantContextAccessor, - ILogger logger) - : IStoreSchedulerService -{ - /// - public async Task AutoSwitchBusinessStatusAsync(DateTime now, CancellationToken cancellationToken) - { - var currentTenantId = tenantContextAccessor.Current?.TenantId ?? 0; - if (currentTenantId != 0) - { - return await AutoSwitchBusinessStatusSingleTenantAsync(now, cancellationToken); - } - - var tenants = await context.Tenants - .AsNoTracking() - .Where(x => x.DeletedAt == null && x.Id > 0) - .Select(x => new { x.Id, x.Code }) - .ToListAsync(cancellationToken); - if (tenants.Count == 0) - { - return 0; - } - - var totalUpdated = 0; - foreach (var tenant in tenants) - { - using (tenantContextAccessor.EnterTenantScope(tenant.Id, "scheduler", tenant.Code)) - { - totalUpdated += await AutoSwitchBusinessStatusSingleTenantAsync(now, cancellationToken); - } - } - - return totalUpdated; - } - - private async Task AutoSwitchBusinessStatusSingleTenantAsync(DateTime now, CancellationToken cancellationToken) - { - // 1. 读取候选门店 - var stores = await context.Stores - .Where(store => store.DeletedAt == null - && store.AuditStatus == StoreAuditStatus.Activated - && store.BusinessStatus != StoreBusinessStatus.ForceClosed) - .ToListAsync(cancellationToken); - if (stores.Count == 0) - { - return 0; - } - - // 2. (空行后) 读取营业时段与休息日 - var storeIds = stores.Select(store => store.Id).ToArray(); - var hours = await context.StoreBusinessHours - .AsNoTracking() - .Where(hour => storeIds.Contains(hour.StoreId)) - .ToListAsync(cancellationToken); - var today = now.Date; - var holidays = await context.StoreHolidays - .AsNoTracking() - .Where(holiday => storeIds.Contains(holiday.StoreId) - && holiday.Date <= today - && (holiday.EndDate == null || holiday.EndDate >= today)) - .ToListAsync(cancellationToken); - - // 3. (空行后) 构造查找表 - var hoursLookup = hours - .GroupBy(hour => hour.StoreId) - .ToDictionary(group => group.Key, group => (IReadOnlyList)group.ToList()); - var holidayLookup = holidays - .GroupBy(holiday => holiday.StoreId) - .ToDictionary(group => group.Key, group => (IReadOnlyList)group.ToList()); - - // 4. (空行后) 判定状态并更新 - var updated = 0; - foreach (var store in stores) - { - // 4.1 跳过强制关闭门店 - if (store.BusinessStatus == StoreBusinessStatus.ForceClosed) - { - continue; - } - - // 4.2 (空行后) 尊重手动歇业原因 - if (store.ClosureReason.HasValue && store.ClosureReason != StoreClosureReason.OutOfBusinessHours) - { - continue; - } - - // 4.3 (空行后) 计算营业状态 - var storeHolidays = holidayLookup.TryGetValue(store.Id, out var matched) ? matched : []; - var nowTime = now.TimeOfDay; - var isHolidayClosed = storeHolidays.Any(holiday => - holiday.OverrideType == OverrideType.Closed && IsWithinHolidayTime(holiday, nowTime)); - var hasModifiedHours = storeHolidays.Any(holiday => holiday.OverrideType == OverrideType.ModifiedHours); - var isModifiedOpen = hasModifiedHours && storeHolidays.Any(holiday => - holiday.OverrideType == OverrideType.ModifiedHours && IsWithinHolidayTime(holiday, nowTime)); - var isTemporaryOpen = storeHolidays.Any(holiday => - holiday.OverrideType == OverrideType.TemporaryOpen && IsWithinHolidayTime(holiday, nowTime)); - var hasHours = hoursLookup.TryGetValue(store.Id, out var storeHours) && storeHours.Count > 0; - var isOpen = false; - if (isHolidayClosed) - { - isOpen = false; - } - else if (hasModifiedHours) - { - isOpen = isModifiedOpen; - } - else - { - isOpen = hasHours && IsWithinBusinessHours(storeHours ?? [], now); - if (!isOpen && isTemporaryOpen) - { - isOpen = true; - } - } - if (isOpen) - { - if (store.BusinessStatus != StoreBusinessStatus.Open) - { - store.BusinessStatus = StoreBusinessStatus.Open; - store.ClosureReason = null; - store.ClosureReasonText = null; - updated++; - } - continue; - } - - // 4.4 (空行后) 非营业时段切换为休息 - if (store.BusinessStatus != StoreBusinessStatus.Resting || store.ClosureReason != StoreClosureReason.OutOfBusinessHours) - { - store.BusinessStatus = StoreBusinessStatus.Resting; - store.ClosureReason = StoreClosureReason.OutOfBusinessHours; - store.ClosureReasonText = "非营业时间自动休息"; - updated++; - } - } - - // 5. (空行后) 保存变更并记录日志 - if (updated > 0) - { - await context.SaveChangesAsync(cancellationToken); - } - - logger.LogInformation("定时任务:营业状态自动切换完成,更新 {UpdatedCount} 家门店", updated); - return updated; - } - - /// - public async Task CheckQualificationExpiryAsync(DateTime now, CancellationToken cancellationToken) - { - var currentTenantId = tenantContextAccessor.Current?.TenantId ?? 0; - if (currentTenantId != 0) - { - return await CheckQualificationExpirySingleTenantAsync(now, cancellationToken); - } - - var tenants = await context.Tenants - .AsNoTracking() - .Where(x => x.DeletedAt == null && x.Id > 0) - .Select(x => new { x.Id, x.Code }) - .ToListAsync(cancellationToken); - if (tenants.Count == 0) - { - return 0; - } - - var totalUpdated = 0; - foreach (var tenant in tenants) - { - using (tenantContextAccessor.EnterTenantScope(tenant.Id, "scheduler", tenant.Code)) - { - totalUpdated += await CheckQualificationExpirySingleTenantAsync(now, cancellationToken); - } - } - - return totalUpdated; - } - - private async Task CheckQualificationExpirySingleTenantAsync(DateTime now, CancellationToken cancellationToken) - { - // 1. 查询过期门店 - var today = DateOnly.FromDateTime(now); - var expiredStoreIds = await context.StoreQualifications - .AsNoTracking() - .Where(qualification => qualification.DeletedAt == null - && qualification.ExpiresAt.HasValue - && qualification.ExpiresAt.Value < today) - .Select(qualification => qualification.StoreId) - .Distinct() - .ToListAsync(cancellationToken); - if (expiredStoreIds.Count == 0) - { - return 0; - } - - // 2. (空行后) 加载门店并更新状态 - var stores = await context.Stores - .Where(store => expiredStoreIds.Contains(store.Id) - && store.DeletedAt == null - && store.AuditStatus == StoreAuditStatus.Activated - && store.BusinessStatus != StoreBusinessStatus.ForceClosed) - .ToListAsync(cancellationToken); - - var updated = 0; - foreach (var store in stores) - { - // 2.1 跳过已标记过期门店 - if (store.BusinessStatus == StoreBusinessStatus.Resting && store.ClosureReason == StoreClosureReason.LicenseExpired) - { - continue; - } - - // 2.2 (空行后) 设置资质过期状态 - store.BusinessStatus = StoreBusinessStatus.Resting; - store.ClosureReason = StoreClosureReason.LicenseExpired; - store.ClosureReasonText = "证照过期自动休息"; - updated++; - } - - // 3. (空行后) 保存变更并记录日志 - if (updated > 0) - { - await context.SaveChangesAsync(cancellationToken); - } - - logger.LogInformation("定时任务:资质过期检查完成,更新 {UpdatedCount} 家门店", updated); - return updated; - } - - private static bool IsWithinBusinessHours(IReadOnlyList hours, DateTime now) - { - // 1. 提取当前时间 - var day = now.DayOfWeek; - var time = now.TimeOfDay; - - foreach (var hour in hours) - { - if (hour.HourType == BusinessHourType.Closed) - { - continue; - } - if (hour.StartTime == hour.EndTime) - { - continue; - } - if (hour.StartTime < hour.EndTime) - { - if (hour.DayOfWeek == day && time >= hour.StartTime && time < hour.EndTime) - { - return true; - } - continue; - } - var nextDay = NextDay(hour.DayOfWeek); - if (hour.DayOfWeek == day && time >= hour.StartTime) - { - return true; - } - if (nextDay == day && time < hour.EndTime) - { - return true; - } - } - - return false; - } - - private static bool IsWithinHolidayTime(StoreHoliday holiday, TimeSpan time) - { - if (holiday.IsAllDay) - { - return true; - } - - if (!holiday.StartTime.HasValue || !holiday.EndTime.HasValue) - { - return false; - } - - return time >= holiday.StartTime.Value && time < holiday.EndTime.Value; - } - - private static DayOfWeek NextDay(DayOfWeek day) - { - var next = (int)day + 1; - return next > 6 ? DayOfWeek.Sunday : (DayOfWeek)next; - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/BackgroundServices/AutoRenewalService.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/BackgroundServices/AutoRenewalService.cs deleted file mode 100644 index bd0944e..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/BackgroundServices/AutoRenewalService.cs +++ /dev/null @@ -1,202 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Infrastructure.App.Persistence; -using TakeoutSaaS.Shared.Abstractions.Ids; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Infrastructure.BackgroundServices; - -/// -/// 自动续费后台服务。 -/// 定期检查开启自动续费的订阅,在到期前自动生成续费账单。 -/// -public sealed class AutoRenewalService : BackgroundService -{ - private readonly IServiceProvider _serviceProvider; - private readonly ILogger _logger; - private readonly AutoRenewalOptions _options; - - public AutoRenewalService( - IServiceProvider serviceProvider, - ILogger logger, - IOptions options) - { - _serviceProvider = serviceProvider; - _logger = logger; - _options = options.Value; - } - - protected override async Task ExecuteAsync(CancellationToken stoppingToken) - { - _logger.LogInformation("自动续费服务已启动"); - - while (!stoppingToken.IsCancellationRequested) - { - try - { - // 计算下次执行时间(每天执行) - var now = DateTime.UtcNow; - var nextRun = now.Date.AddDays(1).AddHours(_options.ExecuteHour); - var delay = nextRun - now; - - _logger.LogInformation("自动续费服务将在 {NextRun} 执行,等待 {Delay}", nextRun, delay); - - await Task.Delay(delay, stoppingToken); - - if (stoppingToken.IsCancellationRequested) - break; - - await ProcessAutoRenewalsAsync(stoppingToken); - } - catch (Exception ex) - { - _logger.LogError(ex, "自动续费服务执行异常"); - // 出错后等待一段时间再重试 - await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken); - } - } - - _logger.LogInformation("自动续费服务已停止"); - } - - private async Task ProcessAutoRenewalsAsync(CancellationToken cancellationToken) - { - _logger.LogInformation("开始处理自动续费"); - - using var scope = _serviceProvider.CreateScope(); - var dbContext = scope.ServiceProvider.GetRequiredService(); - var idGenerator = scope.ServiceProvider.GetRequiredService(); - var tenantContextAccessor = scope.ServiceProvider.GetRequiredService(); - - var now = DateTime.UtcNow; - var renewalThreshold = now.AddDays(_options.RenewalDaysBeforeExpiry); - - try - { - var tenants = await dbContext.Tenants - .AsNoTracking() - .Where(x => x.DeletedAt == null && x.Id > 0) - .Select(x => new { x.Id, x.Code }) - .ToListAsync(cancellationToken); - if (tenants.Count == 0) - { - _logger.LogInformation("自动续费处理完成:未找到可处理租户"); - return; - } - - var billsCreatedTotal = 0; - foreach (var tenant in tenants) - { - using (tenantContextAccessor.EnterTenantScope(tenant.Id, "background:auto-renewal", tenant.Code)) - { - var billsCreated = 0; - - // 查询开启自动续费且即将到期的活跃订阅 - var autoRenewSubscriptions = await dbContext.TenantSubscriptions - .Where(s => s.Status == SubscriptionStatus.Active - && s.AutoRenew - && s.EffectiveTo <= renewalThreshold - && s.EffectiveTo > now) - .Join( - dbContext.TenantPackages, - sub => sub.TenantPackageId, - package => package.Id, - (sub, package) => new { Subscription = sub, Package = package } - ) - .ToListAsync(cancellationToken); - - foreach (var item in autoRenewSubscriptions) - { - // 检查是否已为本次到期生成过账单 - var existingBill = await dbContext.TenantBillingStatements - .AnyAsync(b => b.TenantId == item.Subscription.TenantId - && b.PeriodStart >= item.Subscription.EffectiveTo - && b.Status != TenantBillingStatus.Cancelled, - cancellationToken); - - if (existingBill) - { - _logger.LogInformation( - "订阅 {SubscriptionId} 已存在续费账单,跳过", - item.Subscription.Id); - continue; - } - - // 生成续费账单 - var billNo = $"BILL-{DateTime.UtcNow:yyyyMMddHHmmss}-{item.Subscription.TenantId}"; - var periodStart = item.Subscription.EffectiveTo; - - // 从当前订阅计算续费周期(月数) - var currentDurationMonths = ((item.Subscription.EffectiveTo.Year - item.Subscription.EffectiveFrom.Year) * 12) - + item.Subscription.EffectiveTo.Month - item.Subscription.EffectiveFrom.Month; - if (currentDurationMonths <= 0) currentDurationMonths = 1; // 至少1个月 - - var periodEnd = periodStart.AddMonths(currentDurationMonths); - - // 根据续费周期计算价格(年付优惠) - var renewalPrice = currentDurationMonths >= 12 - ? (item.Package.YearlyPrice ?? item.Package.MonthlyPrice * 12 ?? 0) - : (item.Package.MonthlyPrice ?? 0) * currentDurationMonths; - - var bill = new TenantBillingStatement - { - Id = idGenerator.NextId(), - TenantId = item.Subscription.TenantId, - StatementNo = billNo, - PeriodStart = periodStart, - PeriodEnd = periodEnd, - AmountDue = renewalPrice, - AmountPaid = 0, - Status = TenantBillingStatus.Pending, - DueDate = periodStart.AddDays(-1), // 到期前一天为付款截止日 - LineItemsJson = $"{{\"套餐名称\":\"{item.Package.Name}\",\"续费周期\":\"{currentDurationMonths}个月\"}}", - CreatedAt = DateTime.UtcNow - }; - - dbContext.TenantBillingStatements.Add(bill); - billsCreated++; - - _logger.LogInformation( - "为订阅 {SubscriptionId} (租户 {TenantId}) 生成自动续费账单 {BillNo},金额 {Amount}", - item.Subscription.Id, item.Subscription.TenantId, billNo, renewalPrice); - } - - if (billsCreated > 0) - { - await dbContext.SaveChangesAsync(cancellationToken); - } - - billsCreatedTotal += billsCreated; - } - } - - _logger.LogInformation("自动续费处理完成,共生成 {Count} 张账单", billsCreatedTotal); - } - catch (Exception ex) - { - _logger.LogError(ex, "自动续费处理失败"); - throw; - } - } -} - -/// -/// 自动续费配置选项。 -/// -public sealed class AutoRenewalOptions -{ - /// - /// 执行时间(小时,UTC时间),默认凌晨1点。 - /// - public int ExecuteHour { get; set; } = 1; - - /// - /// 在到期前N天生成续费账单,默认3天。 - /// - public int RenewalDaysBeforeExpiry { get; set; } = 3; -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/BackgroundServices/RenewalReminderService.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/BackgroundServices/RenewalReminderService.cs deleted file mode 100644 index c587830..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/BackgroundServices/RenewalReminderService.cs +++ /dev/null @@ -1,191 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Infrastructure.App.Persistence; -using TakeoutSaaS.Shared.Abstractions.Ids; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Infrastructure.BackgroundServices; - -/// -/// 续费提醒后台服务。 -/// 定期检查即将到期的订阅,发送续费提醒通知。 -/// -public sealed class RenewalReminderService : BackgroundService -{ - private readonly IServiceProvider _serviceProvider; - private readonly ILogger _logger; - private readonly RenewalReminderOptions _options; - - public RenewalReminderService( - IServiceProvider serviceProvider, - ILogger logger, - IOptions options) - { - _serviceProvider = serviceProvider; - _logger = logger; - _options = options.Value; - } - - protected override async Task ExecuteAsync(CancellationToken stoppingToken) - { - _logger.LogInformation("续费提醒服务已启动"); - - while (!stoppingToken.IsCancellationRequested) - { - try - { - // 计算下次执行时间(每天执行) - var now = DateTime.UtcNow; - var nextRun = now.Date.AddDays(1).AddHours(_options.ExecuteHour); - var delay = nextRun - now; - - _logger.LogInformation("续费提醒服务将在 {NextRun} 执行,等待 {Delay}", nextRun, delay); - - await Task.Delay(delay, stoppingToken); - - if (stoppingToken.IsCancellationRequested) - break; - - await SendRenewalRemindersAsync(stoppingToken); - } - catch (Exception ex) - { - _logger.LogError(ex, "续费提醒服务执行异常"); - // 出错后等待一段时间再重试 - await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken); - } - } - - _logger.LogInformation("续费提醒服务已停止"); - } - - private async Task SendRenewalRemindersAsync(CancellationToken cancellationToken) - { - _logger.LogInformation("开始发送续费提醒"); - - using var scope = _serviceProvider.CreateScope(); - var dbContext = scope.ServiceProvider.GetRequiredService(); - var idGenerator = scope.ServiceProvider.GetRequiredService(); - var tenantContextAccessor = scope.ServiceProvider.GetRequiredService(); - - var now = DateTime.UtcNow; - - try - { - var tenants = await dbContext.Tenants - .AsNoTracking() - .Where(x => x.DeletedAt == null && x.Id > 0) - .Select(x => new { x.Id, x.Code, x.Name }) - .ToListAsync(cancellationToken); - if (tenants.Count == 0) - { - _logger.LogInformation("续费提醒发送完成:未找到可处理租户"); - return; - } - - var remindersSentTotal = 0; - foreach (var tenant in tenants) - { - using (tenantContextAccessor.EnterTenantScope(tenant.Id, "background:renewal-reminder", tenant.Code)) - { - var remindersSent = 0; - - // 遍历配置的提醒时间点(例如:到期前7天、3天、1天) - foreach (var daysBeforeExpiry in _options.ReminderDaysBeforeExpiry) - { - var targetDate = now.AddDays(daysBeforeExpiry); - var startOfDay = targetDate.Date; - var endOfDay = startOfDay.AddDays(1); - - // 查询即将到期的活跃订阅(且未开启自动续费) - var expiringSubscriptions = await dbContext.TenantSubscriptions - .Where(s => s.Status == SubscriptionStatus.Active - && !s.AutoRenew - && s.EffectiveTo >= startOfDay - && s.EffectiveTo < endOfDay) - .Join( - dbContext.TenantPackages, - sub => sub.TenantPackageId, - package => package.Id, - (sub, package) => new { Subscription = sub, Package = package } - ) - .ToListAsync(cancellationToken); - - foreach (var item in expiringSubscriptions) - { - // 检查是否已发送过相同天数的提醒(避免重复发送) - var alreadySent = await dbContext.TenantNotifications - .AnyAsync(n => n.TenantId == item.Subscription.TenantId - && n.Message.Contains($"{daysBeforeExpiry}天内到期") - && n.SentAt >= now.AddHours(-24), // 24小时内已发送过 - cancellationToken); - - if (alreadySent) - { - continue; - } - - // 创建续费提醒通知 - var notification = new TenantNotification - { - Id = idGenerator.NextId(), - TenantId = item.Subscription.TenantId, - Title = "订阅续费提醒", - Message = $"您的订阅套餐「{item.Package.Name}」将在 {daysBeforeExpiry} 天内到期(到期时间:{item.Subscription.EffectiveTo:yyyy-MM-dd HH:mm}),请及时续费以免影响使用。", - Severity = daysBeforeExpiry <= 1 - ? TenantNotificationSeverity.Critical - : TenantNotificationSeverity.Warning, - Channel = TenantNotificationChannel.InApp, - SentAt = DateTime.UtcNow, - ReadAt = null, - CreatedAt = DateTime.UtcNow - }; - - dbContext.TenantNotifications.Add(notification); - remindersSent++; - - _logger.LogInformation( - "发送续费提醒: 租户 {TenantName} ({TenantId}), 套餐 {PackageName}, 剩余 {Days} 天", - tenant.Name, item.Subscription.TenantId, item.Package.Name, daysBeforeExpiry); - } - } - - if (remindersSent > 0) - { - await dbContext.SaveChangesAsync(cancellationToken); - } - - remindersSentTotal += remindersSent; - } - } - - _logger.LogInformation("续费提醒发送完成,共发送 {Count} 条提醒", remindersSentTotal); - } - catch (Exception ex) - { - _logger.LogError(ex, "发送续费提醒失败"); - throw; - } - } -} - -/// -/// 续费提醒配置选项。 -/// -public sealed class RenewalReminderOptions -{ - /// - /// 执行时间(小时,UTC时间),默认上午10点。 - /// - public int ExecuteHour { get; set; } = 10; - - /// - /// 提醒时间点(到期前N天),默认7天、3天、1天。 - /// - public int[] ReminderDaysBeforeExpiry { get; set; } = { 7, 3, 1 }; -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/BackgroundServices/SubscriptionExpiryCheckService.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/BackgroundServices/SubscriptionExpiryCheckService.cs deleted file mode 100644 index 3057243..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/BackgroundServices/SubscriptionExpiryCheckService.cs +++ /dev/null @@ -1,158 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using TakeoutSaaS.Domain.Tenants.Enums; -using TakeoutSaaS.Infrastructure.App.Persistence; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Infrastructure.BackgroundServices; - -/// -/// 订阅到期检查后台服务。 -/// 每天凌晨执行,检查即将到期和已到期的订阅,自动更新状态。 -/// -public sealed class SubscriptionExpiryCheckService : BackgroundService -{ - private readonly IServiceProvider _serviceProvider; - private readonly ILogger _logger; - private readonly SubscriptionExpiryCheckOptions _options; - - public SubscriptionExpiryCheckService( - IServiceProvider serviceProvider, - ILogger logger, - IOptions options) - { - _serviceProvider = serviceProvider; - _logger = logger; - _options = options.Value; - } - - protected override async Task ExecuteAsync(CancellationToken stoppingToken) - { - _logger.LogInformation("订阅到期检查服务已启动"); - - while (!stoppingToken.IsCancellationRequested) - { - try - { - // 计算下次执行时间(每天凌晨) - var now = DateTime.UtcNow; - var nextRun = now.Date.AddDays(1).AddHours(_options.ExecuteHour); - var delay = nextRun - now; - - _logger.LogInformation("订阅到期检查服务将在 {NextRun} 执行,等待 {Delay}", nextRun, delay); - - await Task.Delay(delay, stoppingToken); - - if (stoppingToken.IsCancellationRequested) - break; - - await CheckExpiringSubscriptionsAsync(stoppingToken); - } - catch (Exception ex) - { - _logger.LogError(ex, "订阅到期检查服务执行异常"); - // 出错后等待一段时间再重试 - await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken); - } - } - - _logger.LogInformation("订阅到期检查服务已停止"); - } - - private async Task CheckExpiringSubscriptionsAsync(CancellationToken cancellationToken) - { - _logger.LogInformation("开始执行订阅到期检查"); - - using var scope = _serviceProvider.CreateScope(); - var dbContext = scope.ServiceProvider.GetRequiredService(); - var tenantContextAccessor = scope.ServiceProvider.GetRequiredService(); - - var now = DateTime.UtcNow; - var gracePeriodDays = _options.GracePeriodDays; - - try - { - var tenants = await dbContext.Tenants - .AsNoTracking() - .Where(x => x.DeletedAt == null && x.Id > 0) - .Select(x => new { x.Id, x.Code }) - .ToListAsync(cancellationToken); - if (tenants.Count == 0) - { - _logger.LogInformation("订阅到期检查完成:未找到可处理租户"); - return; - } - - var changedTotal = 0; - var expiredTotal = 0; - var suspendedTotal = 0; - foreach (var tenant in tenants) - { - using (tenantContextAccessor.EnterTenantScope(tenant.Id, "background:subscription-expiry", tenant.Code)) - { - // 1. 检查活跃订阅中已到期的,转为宽限期 - var expiredActive = await dbContext.TenantSubscriptions - .Where(s => s.Status == SubscriptionStatus.Active && s.EffectiveTo < now) - .ToListAsync(cancellationToken); - - foreach (var subscription in expiredActive) - { - subscription.Status = SubscriptionStatus.GracePeriod; - _logger.LogInformation( - "订阅 {SubscriptionId} (租户 {TenantId}) 已到期,进入宽限期", - subscription.Id, subscription.TenantId); - } - - // 2. 检查宽限期订阅中超过宽限期的,转为暂停 - var gracePeriodExpired = await dbContext.TenantSubscriptions - .Where(s => s.Status == SubscriptionStatus.GracePeriod - && s.EffectiveTo.AddDays(gracePeriodDays) < now) - .ToListAsync(cancellationToken); - - foreach (var subscription in gracePeriodExpired) - { - subscription.Status = SubscriptionStatus.Suspended; - _logger.LogInformation( - "订阅 {SubscriptionId} (租户 {TenantId}) 宽限期已结束,已暂停", - subscription.Id, subscription.TenantId); - } - - // 3. 保存更改(逐租户保存,避免跨租户写入) - var changedCount = await dbContext.SaveChangesAsync(cancellationToken); - - changedTotal += changedCount; - expiredTotal += expiredActive.Count; - suspendedTotal += gracePeriodExpired.Count; - } - } - - _logger.LogInformation( - "订阅到期检查完成,共更新 {Count} 条记录 (到期转宽限期: {ExpiredCount}, 宽限期转暂停: {SuspendedCount})", - changedTotal, expiredTotal, suspendedTotal); - } - catch (Exception ex) - { - _logger.LogError(ex, "订阅到期检查失败"); - throw; - } - } -} - -/// -/// 订阅到期检查配置选项。 -/// -public sealed class SubscriptionExpiryCheckOptions -{ - /// - /// 执行时间(小时,UTC时间),默认凌晨2点。 - /// - public int ExecuteHour { get; set; } = 2; - - /// - /// 宽限期天数,默认7天。 - /// - public int GracePeriodDays { get; set; } = 7; -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Extensions/DatabaseServiceCollectionExtensions.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Extensions/DatabaseServiceCollectionExtensions.cs deleted file mode 100644 index e9940a0..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Extensions/DatabaseServiceCollectionExtensions.cs +++ /dev/null @@ -1,102 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using TakeoutSaaS.Infrastructure.Common.Options; -using TakeoutSaaS.Infrastructure.Common.Persistence; -using TakeoutSaaS.Shared.Abstractions.Data; -using TakeoutSaaS.Shared.Abstractions.Ids; -using TakeoutSaaS.Shared.Kernel.Ids; - -namespace TakeoutSaaS.Infrastructure.Common.Extensions; - -/// -/// 数据访问与多数据源相关的服务注册扩展。 -/// -public static class DatabaseServiceCollectionExtensions -{ - /// - /// 注册数据库基础设施(多数据源配置、读写分离、Dapper 执行器)。 - /// - /// 服务集合。 - /// 配置源。 - /// 服务集合。 - public static IServiceCollection AddDatabaseInfrastructure(this IServiceCollection services, IConfiguration configuration) - { - services.AddOptions() - .Bind(configuration.GetSection(DatabaseOptions.SectionName)) - .ValidateDataAnnotations() - .ValidateOnStart(); - - services.AddOptions() - .Bind(configuration.GetSection(IdGeneratorOptions.SectionName)) - .ValidateDataAnnotations() - .ValidateOnStart(); - - services.AddSingleton(sp => - { - var options = sp.GetRequiredService>().Value; - return new SnowflakeIdGenerator(options.WorkerId, options.DatacenterId); - }); - - services.AddSingleton(); - services.AddScoped(); - return services; - } - - /// - /// 为指定 DbContext 注册读写分离的 PostgreSQL 配置,同时提供读上下文工厂。 - /// - /// 上下文类型。 - /// 服务集合。 - /// 逻辑数据源名称。 - /// 服务集合。 - public static IServiceCollection AddPostgresDbContext( - this IServiceCollection services, - string dataSourceName) - where TContext : DbContext - { - services.AddDbContext( - (sp, options) => - { - ConfigureDbContextOptions(sp, options, dataSourceName, DatabaseConnectionRole.Write); - }, - contextLifetime: ServiceLifetime.Scoped, - optionsLifetime: ServiceLifetime.Singleton); - - services.AddDbContextFactory((sp, options) => - { - ConfigureDbContextOptions(sp, options, dataSourceName, DatabaseConnectionRole.Read); - }); - - return services; - } - - /// - /// 配置 DbContextOptions,应用连接串、命令超时与重试策略。 - /// - /// 服务提供程序。 - /// 上下文配置器。 - /// 数据源名称。 - /// 连接角色。 - private static void ConfigureDbContextOptions( - IServiceProvider serviceProvider, - DbContextOptionsBuilder optionsBuilder, - string dataSourceName, - DatabaseConnectionRole role) - { - var connection = serviceProvider - .GetRequiredService() - .GetConnection(dataSourceName, role); - - optionsBuilder.UseNpgsql( - connection.ConnectionString, - npgsqlOptions => - { - npgsqlOptions.CommandTimeout(connection.CommandTimeoutSeconds); - npgsqlOptions.EnableRetryOnFailure( - connection.MaxRetryCount, - TimeSpan.FromSeconds(connection.MaxRetryDelaySeconds), - null); - }); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Options/DatabaseDataSourceOptions.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Options/DatabaseDataSourceOptions.cs deleted file mode 100644 index 694c9e3..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Options/DatabaseDataSourceOptions.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Infrastructure.Common.Options; - -/// -/// 单个数据源的连接配置,支持主写与多个从读。 -/// -public sealed class DatabaseDataSourceOptions -{ - /// - /// 主写连接串,读写分离缺省回退到此连接。 - /// - [Required] - public string? Write { get; set; } - - /// - /// 从读连接串集合,可为空。 - /// - public IList Reads { get; init; } = new List(); - - /// - /// 默认命令超时(秒),未设置时使用框架默认值。 - /// - [Range(1, 600)] - public int CommandTimeoutSeconds { get; set; } = 30; - - /// - /// 数据库重试次数。 - /// - [Range(0, 10)] - public int MaxRetryCount { get; set; } = 3; - - /// - /// 数据库重试最大延迟(秒)。 - /// - [Range(1, 60)] - public int MaxRetryDelaySeconds { get; set; } = 5; -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Options/DatabaseOptions.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Options/DatabaseOptions.cs deleted file mode 100644 index a2db8d2..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Options/DatabaseOptions.cs +++ /dev/null @@ -1,33 +0,0 @@ -namespace TakeoutSaaS.Infrastructure.Common.Options; - -/// -/// 数据源配置集合,键为逻辑数据源名称。 -/// -public sealed class DatabaseOptions -{ - /// - /// 配置节名称。 - /// - public const string SectionName = "Database"; - - /// - /// 数据源配置字典,键为数据源名称。 - /// - public IDictionary DataSources { get; init; } = - new Dictionary(StringComparer.OrdinalIgnoreCase); - - /// - /// 获取指定名称的数据源配置,不存在时返回 null。 - /// - /// 逻辑数据源名称。 - /// 数据源配置或 null。 - public DatabaseDataSourceOptions? Find(string name) - { - if (string.IsNullOrWhiteSpace(name)) - { - return null; - } - - return DataSources.TryGetValue(name, out var options) ? options : null; - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/AppDbContext.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/AppDbContext.cs deleted file mode 100644 index 8511816..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/AppDbContext.cs +++ /dev/null @@ -1,239 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; -using System.Reflection; -using TakeoutSaaS.Shared.Abstractions.Entities; -using TakeoutSaaS.Shared.Abstractions.Ids; -using TakeoutSaaS.Shared.Abstractions.Security; - -namespace TakeoutSaaS.Infrastructure.Common.Persistence; - -/// -/// 应用基础 DbContext,统一处理审计字段、软删除与全局查询过滤。 -/// -public abstract class AppDbContext( - DbContextOptions options, - ICurrentUserAccessor? currentUserAccessor = null, - IIdGenerator? idGenerator = null) : DbContext(options) -{ - private readonly ICurrentUserAccessor? _currentUserAccessor = currentUserAccessor; - private readonly IIdGenerator? _idGenerator = idGenerator; - - /// - /// 是否禁用软删除过滤器。 - /// - /// - /// 仅允许在少数系统任务/恢复场景中临时关闭,默认应保持开启。 - /// - protected bool IsSoftDeleteFilterDisabled { get; private set; } - - /// - /// 临时禁用软删除过滤器(仅关闭软删除过滤,不影响租户过滤)。 - /// - /// 作用域对象,释放后恢复之前的过滤状态。 - public IDisposable DisableSoftDeleteFilter() - { - var previous = IsSoftDeleteFilterDisabled; - IsSoftDeleteFilterDisabled = true; - - return new SoftDeleteFilterScope(this, previous); - } - - /// - /// 构建模型时应用软删除过滤器。 - /// - /// 模型构建器。 - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - base.OnModelCreating(modelBuilder); - ApplySoftDeleteQueryFilters(modelBuilder); - modelBuilder.ApplyXmlComments(); - } - - /// - /// 保存更改前应用元数据填充。 - /// - /// 受影响行数。 - public override int SaveChanges() - { - OnBeforeSaving(); - return base.SaveChanges(); - } - - /// - /// 异步保存更改前应用元数据填充。 - /// - /// 取消标记。 - /// 受影响行数。 - public override Task SaveChangesAsync(CancellationToken cancellationToken = default) - { - OnBeforeSaving(); - return base.SaveChangesAsync(cancellationToken); - } - - /// - /// 保存前处理审计、软删除等元数据,可在子类中扩展。 - /// - protected virtual void OnBeforeSaving() - { - ApplyIdGeneration(); - ApplySoftDeleteMetadata(); - ApplyAuditMetadata(); - } - - /// - /// 为新增实体生成雪花 ID。 - /// - private void ApplyIdGeneration() - { - if (_idGenerator == null) - { - return; - } - - foreach (var entry in ChangeTracker.Entries()) - { - if (entry.State != EntityState.Added) - { - continue; - } - - if (entry.Entity.Id == 0) - { - entry.Entity.Id = _idGenerator.NextId(); - } - } - } - - /// - /// 将软删除实体的删除操作转换为设置 DeletedAt。 - /// - private void ApplySoftDeleteMetadata() - { - var utcNow = DateTime.UtcNow; - var actor = GetCurrentUserIdOrNull(); - foreach (var entry in ChangeTracker.Entries()) - { - if (entry.State == EntityState.Added && entry.Entity.DeletedAt.HasValue) - { - entry.Entity.DeletedAt = null; - } - - if (entry.State != EntityState.Deleted) - { - continue; - } - - entry.State = EntityState.Modified; - entry.Entity.DeletedAt = utcNow; - if (entry.Entity is IAuditableEntity auditable) - { - auditable.DeletedBy = actor; - if (!auditable.UpdatedAt.HasValue) - { - auditable.UpdatedAt = utcNow; - auditable.UpdatedBy = actor; - } - } - } - } - - /// - /// 对审计实体填充创建与更新时间。 - /// - private void ApplyAuditMetadata() - { - var utcNow = DateTime.UtcNow; - var actor = GetCurrentUserIdOrNull(); - - foreach (var entry in ChangeTracker.Entries()) - { - if (entry.State == EntityState.Added) - { - entry.Entity.CreatedAt = utcNow; - entry.Entity.UpdatedAt = null; - entry.Entity.CreatedBy ??= actor; - entry.Entity.UpdatedBy = null; - entry.Entity.DeletedBy = null; - entry.Entity.DeletedAt = null; - } - else if (entry.State == EntityState.Modified) - { - entry.Entity.UpdatedAt = utcNow; - entry.Entity.UpdatedBy = actor; - } - } - } - - private long? GetCurrentUserIdOrNull() - { - var userId = _currentUserAccessor?.UserId ?? 0; - return userId == 0 ? null : userId; - } - - /// - /// 应用软删除查询过滤器,自动排除 DeletedAt 不为 null 的记录。 - /// - /// 模型构建器。 - protected void ApplySoftDeleteQueryFilters(ModelBuilder modelBuilder) - { - foreach (var entityType in modelBuilder.Model.GetEntityTypes()) - { - if (!typeof(ISoftDeleteEntity).IsAssignableFrom(entityType.ClrType)) - { - continue; - } - - var methodInfo = typeof(AppDbContext) - .GetMethod(nameof(SetSoftDeleteFilter), BindingFlags.Instance | BindingFlags.NonPublic)! - .MakeGenericMethod(entityType.ClrType); - - methodInfo.Invoke(this, new object[] { modelBuilder }); - } - } - - /// - /// 设置软删除查询过滤器。 - /// - /// 实体类型。 - /// 模型构建器。 - private void SetSoftDeleteFilter(ModelBuilder modelBuilder) - where TEntity : class, ISoftDeleteEntity - { - QueryFilterCombiner.Combine(modelBuilder, "soft_delete", entity => IsSoftDeleteFilterDisabled || entity.DeletedAt == null); - } - - private sealed class SoftDeleteFilterScope(AppDbContext context, bool previous) : IDisposable - { - public void Dispose() - { - context.IsSoftDeleteFilterDisabled = previous; - } - } - - /// - /// 配置审计字段的通用约束。 - /// - /// 实体类型。 - /// 实体构建器。 - protected static void ConfigureAuditableEntity(EntityTypeBuilder builder) - where TEntity : class, IAuditableEntity - { - builder.Property(x => x.CreatedAt).IsRequired(); - builder.Property(x => x.UpdatedAt); - builder.Property(x => x.DeletedAt); - builder.Property(x => x.CreatedBy); - builder.Property(x => x.UpdatedBy); - builder.Property(x => x.DeletedBy); - } - - /// - /// 配置软删除字段的通用约束。 - /// - /// 实体类型。 - /// 实体构建器。 - protected static void ConfigureSoftDeleteEntity(EntityTypeBuilder builder) - where TEntity : class, ISoftDeleteEntity - { - builder.Property(x => x.DeletedAt); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/DapperExecutor.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/DapperExecutor.cs deleted file mode 100644 index d9defe1..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/DapperExecutor.cs +++ /dev/null @@ -1,80 +0,0 @@ -using Microsoft.Extensions.Logging; -using Npgsql; -using System.Data; -using TakeoutSaaS.Shared.Abstractions.Data; - -namespace TakeoutSaaS.Infrastructure.Common.Persistence; - -/// -/// 基于 Dapper 的执行器实现,封装连接创建与读写分离。 -/// -public sealed class DapperExecutor( - IDatabaseConnectionFactory connectionFactory, - ILogger logger) : IDapperExecutor -{ - /// - /// 使用指定数据源与读写角色执行异步查询。 - /// - public async Task QueryAsync( - string dataSourceName, - DatabaseConnectionRole role, - Func> query, - CancellationToken cancellationToken = default) - { - return await ExecuteAsync( - dataSourceName, - role, - async (connection, token) => await query(connection, token), - cancellationToken); - } - - /// - /// 使用指定数据源与读写角色执行异步命令。 - /// - public async Task ExecuteAsync( - string dataSourceName, - DatabaseConnectionRole role, - Func command, - CancellationToken cancellationToken = default) - { - await ExecuteAsync( - dataSourceName, - role, - async (connection, token) => - { - await command(connection, token); - return true; - }, - cancellationToken); - } - - /// - /// 获取默认命令超时时间(秒)。 - /// - public int GetDefaultCommandTimeoutSeconds(string dataSourceName, DatabaseConnectionRole role = DatabaseConnectionRole.Read) - { - var details = connectionFactory.GetConnection(dataSourceName, role); - return details.CommandTimeoutSeconds; - } - - /// - /// 核心执行逻辑:创建连接、打开并执行委托。 - /// - private async Task ExecuteAsync( - string dataSourceName, - DatabaseConnectionRole role, - Func> action, - CancellationToken cancellationToken) - { - var details = connectionFactory.GetConnection(dataSourceName, role); - await using var connection = new NpgsqlConnection(details.ConnectionString); - - logger.LogDebug( - "打开数据库连接:DataSource={DataSource} Role={Role}", - dataSourceName, - role); - - await connection.OpenAsync(cancellationToken); - return await action(connection, cancellationToken); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/DatabaseConnectionDetails.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/DatabaseConnectionDetails.cs deleted file mode 100644 index 20e4850..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/DatabaseConnectionDetails.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace TakeoutSaaS.Infrastructure.Common.Persistence; - -/// -/// 数据库连接信息(连接串与超时/重试设置)。 -/// -public sealed record DatabaseConnectionDetails( - string ConnectionString, - int CommandTimeoutSeconds, - int MaxRetryCount, - int MaxRetryDelaySeconds); diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/DatabaseConnectionFactory.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/DatabaseConnectionFactory.cs deleted file mode 100644 index 54fee08..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/DatabaseConnectionFactory.cs +++ /dev/null @@ -1,120 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using System.ComponentModel.DataAnnotations; -using System.Security.Cryptography; -using TakeoutSaaS.Infrastructure.Common.Options; -using TakeoutSaaS.Shared.Abstractions.Data; - -namespace TakeoutSaaS.Infrastructure.Common.Persistence; - -/// -/// 数据库连接工厂,支持读写分离及连接配置校验。 -/// -public sealed class DatabaseConnectionFactory( - IOptionsMonitor optionsMonitor, - IConfiguration configuration, - ILogger logger) : IDatabaseConnectionFactory -{ - private const int DefaultCommandTimeoutSeconds = 30; - private const int DefaultMaxRetryCount = 3; - private const int DefaultMaxRetryDelaySeconds = 5; - - /// - /// 获取指定数据源与读写角色的连接信息。 - /// - /// 逻辑数据源名称。 - /// 连接角色。 - /// 连接串与超时/重试配置。 - public DatabaseConnectionDetails GetConnection(string dataSourceName, DatabaseConnectionRole role) - { - if (string.IsNullOrWhiteSpace(dataSourceName)) - { - logger.LogWarning("请求的数据源名称为空,使用默认连接。"); - return BuildFallbackConnection(); - } - - var options = optionsMonitor.CurrentValue.Find(dataSourceName); - if (options != null) - { - if (!ValidateOptions(dataSourceName, options)) - { - return BuildFallbackConnection(); - } - - var connectionString = ResolveConnectionString(options, role); - return new DatabaseConnectionDetails( - connectionString, - options.CommandTimeoutSeconds, - options.MaxRetryCount, - options.MaxRetryDelaySeconds); - } - - var fallback = configuration.GetConnectionString(dataSourceName); - if (string.IsNullOrWhiteSpace(fallback)) - { - logger.LogError("缺少数据源 {DataSource} 的连接配置,回退到默认本地连接。", dataSourceName); - return BuildFallbackConnection(); - } - - logger.LogWarning("未找到数据源 {DataSource} 的 Database 节配置,回退使用 ConnectionStrings。", dataSourceName); - return new DatabaseConnectionDetails( - fallback, - DefaultCommandTimeoutSeconds, - DefaultMaxRetryCount, - DefaultMaxRetryDelaySeconds); - } - - /// - /// 校验数据源配置完整性。 - /// - /// 数据源名称。 - /// 数据源配置。 - /// 配置不合法时抛出。 - private bool ValidateOptions(string dataSourceName, DatabaseDataSourceOptions options) - { - var results = new List(); - var context = new ValidationContext(options); - if (!Validator.TryValidateObject(options, context, results, validateAllProperties: true)) - { - var errorMessages = string.Join("; ", results.Select(result => result.ErrorMessage)); - logger.LogError("数据源 {DataSource} 配置非法:{Errors},回退到默认连接。", dataSourceName, errorMessages); - return false; - } - - return true; - } - - /// - /// 根据读写角色选择连接串,从读连接随机分配。 - /// - /// 数据源配置。 - /// 连接角色。 - /// 可用连接串。 - private string ResolveConnectionString(DatabaseDataSourceOptions options, DatabaseConnectionRole role) - { - if (role == DatabaseConnectionRole.Read && options.Reads.Count > 0) - { - var index = RandomNumberGenerator.GetInt32(options.Reads.Count); - return options.Reads[index]; - } - - if (string.IsNullOrWhiteSpace(options.Write)) - { - return BuildFallbackConnection().ConnectionString; - } - - return options.Write; - } - - private DatabaseConnectionDetails BuildFallbackConnection() - { - const string fallback = "Host=120.53.222.17;Port=5432;Database=postgres;Username=postgres;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=1;Maximum Pool Size=20"; - logger.LogWarning("使用默认回退连接串:{Connection}", fallback); - return new DatabaseConnectionDetails( - fallback, - DefaultCommandTimeoutSeconds, - DefaultMaxRetryCount, - DefaultMaxRetryDelaySeconds); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/DesignTime/DesignTimeDbContextFactoryBase.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/DesignTime/DesignTimeDbContextFactoryBase.cs deleted file mode 100644 index 69cebbb..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/DesignTime/DesignTimeDbContextFactoryBase.cs +++ /dev/null @@ -1,178 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Design; -using Microsoft.Extensions.Configuration; -using TakeoutSaaS.Infrastructure.Common.Options; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Infrastructure.Common.Persistence.DesignTime; - -/// -/// EF Core 设计时 DbContext 工厂基类,统一读取 appsettings 中的数据库配置。 -/// -internal abstract class DesignTimeDbContextFactoryBase : IDesignTimeDbContextFactory - where TContext : TenantAwareDbContext -{ - private readonly string _dataSourceName; - private readonly string? _connectionStringEnvVar; - - /// - /// 初始化设计时工厂基类。 - /// - /// 数据源名称。 - /// 连接串环境变量名。 - protected DesignTimeDbContextFactoryBase(string dataSourceName, string? connectionStringEnvVar = null) - { - if (string.IsNullOrWhiteSpace(dataSourceName)) - { - throw new ArgumentException("数据源名称不能为空。", nameof(dataSourceName)); - } - - _dataSourceName = dataSourceName; - _connectionStringEnvVar = connectionStringEnvVar; - } - - /// - /// 创建设计时 DbContext。 - /// - /// 命令行参数。 - /// DbContext 实例。 - public TContext CreateDbContext(string[] args) - { - // 1. 构建 DbContextOptions - var optionsBuilder = new DbContextOptionsBuilder(); - optionsBuilder.UseNpgsql( - ResolveConnectionString(), - npgsql => - { - npgsql.CommandTimeout(30); - npgsql.EnableRetryOnFailure(); - }); - - // 2. 创建上下文 - return CreateContext( - optionsBuilder.Options, - new DesignTimeTenantProvider(), - new DesignTimeCurrentUserAccessor()); - } - - /// - /// 由子类实现的上下文工厂方法。 - /// - /// 上下文选项。 - /// 租户提供器。 - /// 当前用户访问器。 - /// DbContext 实例。 - protected abstract TContext CreateContext( - DbContextOptions options, - ITenantProvider tenantProvider, - ICurrentUserAccessor currentUserAccessor); - - private string ResolveConnectionString() - { - if (!string.IsNullOrWhiteSpace(_connectionStringEnvVar)) - { - var envValue = Environment.GetEnvironmentVariable(_connectionStringEnvVar); - if (!string.IsNullOrWhiteSpace(envValue)) - { - return envValue; - } - } - - var configuration = BuildConfiguration(); - var writeConnection = configuration[$"{DatabaseOptions.SectionName}:DataSources:{_dataSourceName}:Write"]; - if (string.IsNullOrWhiteSpace(writeConnection)) - { - throw new InvalidOperationException( - $"未在配置中找到数据源 '{_dataSourceName}' 的 Write 连接字符串,请检查 appsettings 或设置 {_connectionStringEnvVar ?? "相应"} 环境变量。"); - } - - return writeConnection; - } - - private static IConfigurationRoot BuildConfiguration() - { - var basePath = ResolveConfigurationDirectory(); - var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Development"; - - return new ConfigurationBuilder() - .SetBasePath(basePath) - .AddJsonFile("appsettings.json", optional: true, reloadOnChange: false) - .AddJsonFile($"appsettings.{environment}.json", optional: true, reloadOnChange: false) - .AddEnvironmentVariables() - .Build(); - } - - private static string ResolveConfigurationDirectory() - { - var explicitDir = Environment.GetEnvironmentVariable("TAKEOUTSAAS_APPSETTINGS_DIR"); - if (!string.IsNullOrWhiteSpace(explicitDir) && Directory.Exists(explicitDir)) - { - return explicitDir; - } - - // 1. (空行后) 尝试从当前目录定位解决方案根目录 - var currentDir = Directory.GetCurrentDirectory(); - var solutionRoot = LocateSolutionRoot(currentDir); - - // 2. (空行后) 依次尝试常见 appsettings 目录(仅保留租户管理端 TenantApi) - var candidateDirs = new[] - { - currentDir, - solutionRoot, - solutionRoot is null ? null : Path.Combine(solutionRoot, "src", "Api", "TakeoutSaaS.TenantApi") - }.Where(dir => !string.IsNullOrWhiteSpace(dir)); - - foreach (var dir in candidateDirs) - { - if (dir != null && Directory.Exists(dir) && HasAppSettings(dir)) - { - return dir; - } - } - - throw new InvalidOperationException( - "未找到 appsettings 配置文件,请设置 TAKEOUTSAAS_APPSETTINGS_DIR 环境变量指向包含 appsettings*.json 的目录。"); - } - - private static string? LocateSolutionRoot(string currentPath) - { - var directoryInfo = new DirectoryInfo(currentPath); - while (directoryInfo != null) - { - if (File.Exists(Path.Combine(directoryInfo.FullName, "TakeoutSaaS.sln"))) - { - return directoryInfo.FullName; - } - - directoryInfo = directoryInfo.Parent; - } - - return null; - } - - private static bool HasAppSettings(string directory) => - File.Exists(Path.Combine(directory, "appsettings.json")) || - Directory.GetFiles(directory, "appsettings.*.json").Length > 0; - - private sealed class DesignTimeTenantProvider : ITenantProvider - { - /// - /// 设计时返回默认租户 ID。 - /// - /// 默认租户 ID。 - public long GetCurrentTenantId() => 0; - } - - private sealed class DesignTimeCurrentUserAccessor : ICurrentUserAccessor - { - /// - /// 设计时用户标识。 - /// - public long UserId => 0; - /// - /// 设计时用户鉴权标识。 - /// - public bool IsAuthenticated => false; - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/IDatabaseConnectionFactory.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/IDatabaseConnectionFactory.cs deleted file mode 100644 index 4a684df..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/IDatabaseConnectionFactory.cs +++ /dev/null @@ -1,17 +0,0 @@ -using TakeoutSaaS.Shared.Abstractions.Data; - -namespace TakeoutSaaS.Infrastructure.Common.Persistence; - -/// -/// 数据库连接工厂,负责按读写角色选择对应连接串及配置。 -/// -public interface IDatabaseConnectionFactory -{ - /// - /// 获取指定数据源与读写角色的连接信息。 - /// - /// 逻辑数据源名称。 - /// 连接角色(读/写)。 - /// 连接串与相关配置。 - DatabaseConnectionDetails GetConnection(string dataSourceName, DatabaseConnectionRole role); -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/ModelBuilderCommentExtensions.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/ModelBuilderCommentExtensions.cs deleted file mode 100644 index 810759e..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/ModelBuilderCommentExtensions.cs +++ /dev/null @@ -1,146 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata; -using System.Collections.Concurrent; -using System.Reflection; -using System.Xml.Linq; - -namespace TakeoutSaaS.Infrastructure.Common.Persistence; - -/// -/// Applies XML documentation summaries to EF Core entities/columns as comments. -/// -internal static class ModelBuilderCommentExtensions -{ - /// - /// 将 XML 注释应用到实体与属性的 Comment。 - /// - /// 模型构建器。 - public static void ApplyXmlComments(this ModelBuilder modelBuilder) - { - foreach (var entityType in modelBuilder.Model.GetEntityTypes()) - { - ApplyEntityComment(entityType); - } - } - - private static void ApplyEntityComment(IMutableEntityType entityType) - { - var clrType = entityType.ClrType; - if (clrType == null) - { - return; - } - - if (XmlDocCommentProvider.TryGetSummary(clrType, out var typeComment)) - { - entityType.SetComment(typeComment); - } - - foreach (var property in entityType.GetProperties()) - { - var propertyInfo = property.PropertyInfo; - if (propertyInfo == null) - { - continue; - } - - if (XmlDocCommentProvider.TryGetSummary(propertyInfo, out var propertyComment)) - { - property.SetComment(propertyComment); - } - } - } - - private static class XmlDocCommentProvider - { - private static readonly ConcurrentDictionary> Cache = new(); - - /// - /// 尝试获取成员的摘要注释。 - /// - /// 反射成员。 - /// 输出的摘要文本。 - /// 存在摘要则返回 true。 - public static bool TryGetSummary(MemberInfo member, out string? summary) - { - summary = null; - var assembly = member switch - { - Type type => type.Assembly, - _ => member.DeclaringType?.Assembly - }; - - if (assembly == null) - { - return false; - } - - var map = Cache.GetOrAdd(assembly, LoadComments); - if (map.Count == 0) - { - return false; - } - - var key = GetMemberKey(member); - if (key == null || !map.TryGetValue(key, out var text)) - { - return false; - } - - summary = text; - return true; - } - - private static IReadOnlyDictionary LoadComments(Assembly assembly) - { - var dictionary = new Dictionary(StringComparer.Ordinal); - var xmlPath = Path.ChangeExtension(assembly.Location, ".xml"); - if (string.IsNullOrWhiteSpace(xmlPath) || !File.Exists(xmlPath)) - { - return dictionary; - } - - var document = XDocument.Load(xmlPath); - foreach (var member in document.Descendants("member")) - { - var name = member.Attribute("name")?.Value; - if (string.IsNullOrWhiteSpace(name)) - { - continue; - } - - var summary = member.Element("summary")?.Value; - if (string.IsNullOrWhiteSpace(summary)) - { - continue; - } - - var normalized = Normalize(summary); - if (!string.IsNullOrWhiteSpace(normalized)) - { - dictionary[name] = normalized; - } - } - - return dictionary; - } - - private static string? GetMemberKey(MemberInfo member) => - member switch - { - Type type => $"T:{GetFullName(type)}", - PropertyInfo property => $"P:{GetFullName(property.DeclaringType!)}.{property.Name}", - FieldInfo field => $"F:{GetFullName(field.DeclaringType!)}.{field.Name}", - _ => null - }; - - private static string GetFullName(Type type) => - (type.FullName ?? type.Name).Replace('+', '.'); - - private static string Normalize(string text) - { - var chars = text.Replace('\r', ' ').Replace('\n', ' ').Replace('\t', ' '); - return string.Join(' ', chars.Split(' ', StringSplitOptions.RemoveEmptyEntries)); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/QueryFilterCombiner.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/QueryFilterCombiner.cs deleted file mode 100644 index d9fabf7..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/QueryFilterCombiner.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore; - -namespace TakeoutSaaS.Infrastructure.Common.Persistence; - -/// -/// 查询过滤器合并器:用于追加具名 QueryFilter,避免覆盖已有过滤器。 -/// -internal static class QueryFilterCombiner -{ - /// - /// 为指定实体追加具名查询过滤器。 - /// - /// 实体类型。 - /// 模型构建器。 - /// 过滤器键。 - /// 新增过滤器表达式。 - internal static void Combine(ModelBuilder modelBuilder, string filterKey, Expression> filter) - where TEntity : class - { - modelBuilder.Entity().HasQueryFilter(filterKey, filter); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/TenantAwareDbContext.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/TenantAwareDbContext.cs deleted file mode 100644 index af8e9f8..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/TenantAwareDbContext.cs +++ /dev/null @@ -1,104 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using System.Reflection; -using System.Linq; -using TakeoutSaaS.Shared.Abstractions.Entities; -using TakeoutSaaS.Shared.Abstractions.Ids; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Infrastructure.Common.Persistence; - -/// -/// 多租户感知 DbContext:自动应用租户过滤并填充租户字段。 -/// -public abstract class TenantAwareDbContext( - DbContextOptions options, - ITenantProvider tenantProvider, - ICurrentUserAccessor? currentUserAccessor = null, - IIdGenerator? idGenerator = null) : AppDbContext(options, currentUserAccessor, idGenerator) -{ - private readonly ITenantProvider _tenantProvider = tenantProvider ?? throw new ArgumentNullException(nameof(tenantProvider)); - - /// - /// 当前请求租户 ID。 - /// - protected long CurrentTenantId => _tenantProvider.GetCurrentTenantId(); - - /// - /// 保存前填充租户元数据并执行基础处理。 - /// - protected override void OnBeforeSaving() - { - ApplyTenantMetadata(); - base.OnBeforeSaving(); - } - - /// - /// 应用租户过滤器到所有实现 的实体。 - /// - /// 模型构建器。 - protected void ApplyTenantQueryFilters(ModelBuilder modelBuilder) - { - foreach (var entityType in modelBuilder.Model.GetEntityTypes()) - { - if (!typeof(IMultiTenantEntity).IsAssignableFrom(entityType.ClrType)) - { - continue; - } - - var methodInfo = typeof(TenantAwareDbContext) - .GetMethod(nameof(SetTenantFilter), BindingFlags.Instance | BindingFlags.NonPublic)! - .MakeGenericMethod(entityType.ClrType); - - methodInfo.Invoke(this, new object[] { modelBuilder }); - } - } - - /// - /// 为具体实体设置租户过滤器。 - /// - /// 实体类型。 - /// 模型构建器。 - private void SetTenantFilter(ModelBuilder modelBuilder) - where TEntity : class, IMultiTenantEntity - { - QueryFilterCombiner.Combine(modelBuilder, "tenant", entity => entity.TenantId == CurrentTenantId); - } - - /// - /// 为新增实体填充租户 ID。 - /// - private void ApplyTenantMetadata() - { - var tenantId = CurrentTenantId; - - foreach (var entry in ChangeTracker.Entries()) - { - if (entry.State is EntityState.Detached or EntityState.Unchanged) - { - continue; - } - - if (tenantId == 0) - { - if (entry.Entity.TenantId != 0) - { - throw new InvalidOperationException("未进入租户上下文,禁止写入 TenantId 不为 0 的多租户数据。"); - } - - continue; - } - - if (entry.State == EntityState.Added && entry.Entity.TenantId == 0) - { - entry.Entity.TenantId = tenantId; - continue; - } - - if (entry.Entity.TenantId != tenantId) - { - throw new InvalidOperationException("检测到跨租户写入,已阻止保存。"); - } - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Caching/CacheMetricsCollector.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Caching/CacheMetricsCollector.cs deleted file mode 100644 index 007ba4b..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Caching/CacheMetricsCollector.cs +++ /dev/null @@ -1,212 +0,0 @@ -using System.Collections.Concurrent; -using System.Diagnostics; -using System.Diagnostics.Metrics; - -namespace TakeoutSaaS.Infrastructure.Dictionary.Caching; - -/// -/// 缓存命中/耗时指标采集器。 -/// -public sealed class CacheMetricsCollector -{ - private const string MeterName = "TakeoutSaaS.DictionaryCache"; - private static readonly Meter Meter = new(MeterName, "1.0.0"); - - private readonly Counter _hitCounter; - private readonly Counter _missCounter; - private readonly Counter _invalidationCounter; - private readonly Histogram _durationHistogram; - private readonly ConcurrentQueue _queries = new(); - private readonly TimeSpan _retention = TimeSpan.FromDays(7); - - private long _hitTotal; - private long _missTotal; - - /// - /// 初始化指标采集器。 - /// - public CacheMetricsCollector() - { - _hitCounter = Meter.CreateCounter("cache_hit_count"); - _missCounter = Meter.CreateCounter("cache_miss_count"); - _invalidationCounter = Meter.CreateCounter("cache_invalidation_count"); - _durationHistogram = Meter.CreateHistogram("cache_query_duration_ms"); - - Meter.CreateObservableGauge( - "cache_hit_ratio", - () => new Measurement(CalculateHitRatio())); - } - - /// - /// 记录缓存命中。 - /// - public void RecordHit(string cacheLevel, string dictionaryCode) - { - Interlocked.Increment(ref _hitTotal); - _hitCounter.Add(1, new TagList - { - { "cache_level", cacheLevel }, - { "dictionary_code", NormalizeCode(dictionaryCode) } - }); - } - - /// - /// 记录缓存未命中。 - /// - public void RecordMiss(string cacheLevel, string dictionaryCode) - { - Interlocked.Increment(ref _missTotal); - _missCounter.Add(1, new TagList - { - { "cache_level", cacheLevel }, - { "dictionary_code", NormalizeCode(dictionaryCode) } - }); - } - - /// - /// 记录缓存查询耗时。 - /// - public void RecordDuration(string dictionaryCode, double durationMs) - { - _durationHistogram.Record(durationMs, new TagList - { - { "dictionary_code", NormalizeCode(dictionaryCode) } - }); - } - - /// - /// 记录查询详情,用于统计窗口分析。 - /// - public void RecordQuery(string dictionaryCode, bool l1Hit, bool l2Hit, double durationMs) - { - var record = new CacheQueryRecord(DateTime.UtcNow, NormalizeCode(dictionaryCode), l1Hit, l2Hit, durationMs); - _queries.Enqueue(record); - PruneOldRecords(); - } - - /// - /// 记录缓存失效事件。 - /// - public void RecordInvalidation(string dictionaryCode) - { - _invalidationCounter.Add(1, new TagList - { - { "dictionary_code", NormalizeCode(dictionaryCode) } - }); - } - - /// - /// 获取指定时间范围内的统计快照。 - /// - public CacheStatsSnapshot GetSnapshot(TimeSpan window) - { - var since = DateTime.UtcNow.Subtract(window); - var records = _queries.Where(record => record.Timestamp >= since).ToList(); - - var l1Hits = records.Count(record => record.L1Hit); - var l1Misses = records.Count(record => !record.L1Hit); - var l2Hits = records.Count(record => record.L2Hit); - var l2Misses = records.Count(record => !record.L1Hit && !record.L2Hit); - - var totalHits = l1Hits + l2Hits; - var totalMisses = l1Misses + l2Misses; - var hitRatio = totalHits + totalMisses == 0 ? 0 : totalHits / (double)(totalHits + totalMisses); - var averageDuration = records.Count == 0 ? 0 : records.Average(record => record.DurationMs); - - var topQueried = records - .GroupBy(record => record.DictionaryCode) - .Select(group => new DictionaryQueryCount(group.Key, group.Count())) - .OrderByDescending(item => item.QueryCount) - .Take(5) - .ToList(); - - return new CacheStatsSnapshot( - totalHits, - totalMisses, - hitRatio, - new CacheLevelStats(l1Hits, l2Hits), - new CacheLevelStats(l1Misses, l2Misses), - averageDuration, - topQueried); - } - - /// - /// 从缓存键解析字典编码。 - /// - public static string ExtractDictionaryCode(string cacheKey) - { - if (string.IsNullOrWhiteSpace(cacheKey)) - { - return "unknown"; - } - - if (cacheKey.StartsWith("dict:groups:", StringComparison.Ordinal)) - { - return "groups"; - } - - if (cacheKey.StartsWith("dict:items:", StringComparison.Ordinal)) - { - return "items"; - } - - if (cacheKey.StartsWith("dict:", StringComparison.Ordinal)) - { - var parts = cacheKey.Split(':', StringSplitOptions.RemoveEmptyEntries); - if (parts.Length >= 3) - { - return parts[2]; - } - } - - return "unknown"; - } - - private static string NormalizeCode(string? code) - => string.IsNullOrWhiteSpace(code) ? "unknown" : code.Trim().ToLowerInvariant(); - - private double CalculateHitRatio() - { - var hits = Interlocked.Read(ref _hitTotal); - var misses = Interlocked.Read(ref _missTotal); - return hits + misses == 0 ? 0 : hits / (double)(hits + misses); - } - - private void PruneOldRecords() - { - var cutoff = DateTime.UtcNow.Subtract(_retention); - while (_queries.TryPeek(out var record) && record.Timestamp < cutoff) - { - _queries.TryDequeue(out _); - } - } - - private sealed record CacheQueryRecord( - DateTime Timestamp, - string DictionaryCode, - bool L1Hit, - bool L2Hit, - double DurationMs); -} - -/// -/// 缓存统计快照。 -/// -public sealed record CacheStatsSnapshot( - long TotalHits, - long TotalMisses, - double HitRatio, - CacheLevelStats HitsByLevel, - CacheLevelStats MissesByLevel, - double AverageQueryDurationMs, - IReadOnlyList TopQueriedDictionaries); - -/// -/// 命中统计。 -/// -public sealed record CacheLevelStats(long L1, long L2); - -/// -/// 字典查询次数统计。 -/// -public sealed record DictionaryQueryCount(string Code, int QueryCount); diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Caching/CacheWarmupService.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Caching/CacheWarmupService.cs deleted file mode 100644 index 71af78e..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Caching/CacheWarmupService.cs +++ /dev/null @@ -1,57 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using TakeoutSaaS.Application.Dictionary.Services; -using TakeoutSaaS.Infrastructure.Dictionary.Options; - -namespace TakeoutSaaS.Infrastructure.Dictionary.Caching; - -/// -/// 字典缓存预热服务。 -/// -public sealed class CacheWarmupService( - IServiceScopeFactory scopeFactory, - IOptions options, - ILogger logger) : IHostedService -{ - private const int MaxWarmupCount = 10; - - /// - public async Task StartAsync(CancellationToken cancellationToken) - { - var codes = options.Value.DictionaryCodes - .Where(code => !string.IsNullOrWhiteSpace(code)) - .Select(code => code.Trim()) - .Distinct(StringComparer.OrdinalIgnoreCase) - .Take(MaxWarmupCount) - .ToArray(); - - if (codes.Length == 0) - { - logger.LogInformation("未配置字典缓存预热列表。"); - return; - } - - using var scope = scopeFactory.CreateScope(); - var queryService = scope.ServiceProvider.GetRequiredService(); - - foreach (var code in codes) - { - cancellationToken.ThrowIfCancellationRequested(); - - try - { - await queryService.GetMergedDictionaryAsync(code, cancellationToken); - logger.LogInformation("字典缓存预热完成: {DictionaryCode}", code); - } - catch (Exception ex) - { - logger.LogWarning(ex, "字典缓存预热失败: {DictionaryCode}", code); - } - } - } - - /// - public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Caching/HybridCacheService.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Caching/HybridCacheService.cs deleted file mode 100644 index 5bdb292..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Caching/HybridCacheService.cs +++ /dev/null @@ -1,229 +0,0 @@ -using System.Diagnostics; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using StackExchange.Redis; -using TakeoutSaaS.Application.Dictionary.Abstractions; -using TakeoutSaaS.Domain.Dictionary.Entities; -using TakeoutSaaS.Domain.Dictionary.Enums; -using TakeoutSaaS.Domain.Dictionary.Repositories; -using TakeoutSaaS.Shared.Abstractions.Security; - -namespace TakeoutSaaS.Infrastructure.Dictionary.Caching; - -/// -/// 两级缓存封装:L1 内存 + L2 Redis。 -/// -public sealed class HybridCacheService : IDictionaryHybridCache -{ - private static readonly RedisChannel InvalidationChannel = RedisChannel.Literal("dictionary:cache:invalidate"); - - private readonly MemoryCacheService _memoryCache; - private readonly RedisCacheService _redisCache; - private readonly ISubscriber? _subscriber; - private readonly ILogger? _logger; - private readonly CacheMetricsCollector? _metrics; - private readonly IServiceScopeFactory? _scopeFactory; - - /// - /// 初始化两级缓存服务。 - /// - public HybridCacheService( - MemoryCacheService memoryCache, - RedisCacheService redisCache, - IConnectionMultiplexer? multiplexer = null, - ILogger? logger = null, - CacheMetricsCollector? metrics = null, - IServiceScopeFactory? scopeFactory = null) - { - _memoryCache = memoryCache; - _redisCache = redisCache; - _logger = logger; - _subscriber = multiplexer?.GetSubscriber(); - _metrics = metrics; - _scopeFactory = scopeFactory; - - if (_subscriber != null) - { - _subscriber.Subscribe(InvalidationChannel, (_, value) => - { - var prefix = value.ToString(); - if (!string.IsNullOrWhiteSpace(prefix)) - { - _memoryCache.RemoveByPrefix(prefix); - } - }); - } - } - - /// - /// 获取缓存,如果不存在则创建并回填。 - /// - public async Task GetOrCreateAsync( - string key, - TimeSpan ttl, - Func> factory, - CancellationToken cancellationToken = default) - { - var stopwatch = Stopwatch.StartNew(); - var dictionaryCode = CacheMetricsCollector.ExtractDictionaryCode(key); - var l1Hit = false; - var l2Hit = false; - - var cached = await _memoryCache.GetAsync(key, cancellationToken); - if (cached != null) - { - l1Hit = true; - _metrics?.RecordHit("L1", dictionaryCode); - _metrics?.RecordDuration(dictionaryCode, stopwatch.Elapsed.TotalMilliseconds); - _metrics?.RecordQuery(dictionaryCode, l1Hit, l2Hit, stopwatch.Elapsed.TotalMilliseconds); - return cached; - } - - _metrics?.RecordMiss("L1", dictionaryCode); - - try - { - cached = await _redisCache.GetAsync(key, cancellationToken); - if (cached != null) - { - l2Hit = true; - _metrics?.RecordHit("L2", dictionaryCode); - await _memoryCache.SetAsync(key, cached, ttl, cancellationToken); - _metrics?.RecordDuration(dictionaryCode, stopwatch.Elapsed.TotalMilliseconds); - _metrics?.RecordQuery(dictionaryCode, l1Hit, l2Hit, stopwatch.Elapsed.TotalMilliseconds); - return cached; - } - - _metrics?.RecordMiss("L2", dictionaryCode); - } - catch (Exception ex) - { - _metrics?.RecordMiss("L2", dictionaryCode); - _logger?.LogWarning(ex, "读取 Redis 缓存失败,降级为数据库查询。"); - } - - var created = await factory(cancellationToken); - if (created == null) - { - _metrics?.RecordDuration(dictionaryCode, stopwatch.Elapsed.TotalMilliseconds); - _metrics?.RecordQuery(dictionaryCode, l1Hit, l2Hit, stopwatch.Elapsed.TotalMilliseconds); - return default; - } - - await _memoryCache.SetAsync(key, created, ttl, cancellationToken); - try - { - await _redisCache.SetAsync(key, created, ttl, cancellationToken); - } - catch (Exception ex) - { - _logger?.LogWarning(ex, "写入 Redis 缓存失败。"); - } - - _metrics?.RecordDuration(dictionaryCode, stopwatch.Elapsed.TotalMilliseconds); - _metrics?.RecordQuery(dictionaryCode, l1Hit, l2Hit, stopwatch.Elapsed.TotalMilliseconds); - return created; - } - - /// - /// 失效指定前缀的缓存键。 - /// - public async Task InvalidateAsync( - string prefix, - CacheInvalidationOperation operation = CacheInvalidationOperation.Update, - CancellationToken cancellationToken = default) - { - var dictionaryCode = CacheMetricsCollector.ExtractDictionaryCode(prefix); - _metrics?.RecordInvalidation(dictionaryCode); - - var removedCount = _memoryCache.RemoveByPrefixWithCount(prefix); - long redisRemoved = 0; - try - { - redisRemoved = await _redisCache.RemoveByPrefixWithCountAsync(prefix, cancellationToken); - } - catch (Exception ex) - { - _logger?.LogWarning(ex, "删除 Redis 缓存失败。"); - } - - var totalRemoved = removedCount + (int)Math.Min(redisRemoved, int.MaxValue); - - if (_subscriber != null && !string.IsNullOrWhiteSpace(prefix)) - { - await _subscriber.PublishAsync(InvalidationChannel, prefix); - } - - _ = WriteInvalidationLogAsync(prefix, dictionaryCode, totalRemoved, operation); - } - - private async Task WriteInvalidationLogAsync( - string prefix, - string dictionaryCode, - int removedCount, - CacheInvalidationOperation operation) - { - if (_scopeFactory == null) - { - return; - } - - try - { - using var scope = _scopeFactory.CreateScope(); - var repo = scope.ServiceProvider.GetService(); - if (repo == null) - { - return; - } - - var currentUser = scope.ServiceProvider.GetService(); - var tenantId = TryExtractTenantId(prefix) ?? 0; - var scopeType = tenantId == 0 ? DictionaryScope.System : DictionaryScope.Business; - - var log = new CacheInvalidationLog - { - TenantId = tenantId, - Timestamp = DateTime.UtcNow, - DictionaryCode = dictionaryCode, - Scope = scopeType, - AffectedCacheKeyCount = removedCount, - OperatorId = currentUser?.IsAuthenticated == true ? currentUser.UserId : 0, - Operation = operation - }; - - await repo.AddAsync(log); - await repo.SaveChangesAsync(); - } - catch (Exception ex) - { - _logger?.LogWarning(ex, "写入缓存失效日志失败。"); - } - } - - private static long? TryExtractTenantId(string prefix) - { - if (string.IsNullOrWhiteSpace(prefix)) - { - return null; - } - - if (prefix.StartsWith("dict:groups:", StringComparison.Ordinal)) - { - var token = prefix.Replace("dict:groups:", string.Empty, StringComparison.Ordinal).Trim(':'); - return long.TryParse(token.Split(':', StringSplitOptions.RemoveEmptyEntries).FirstOrDefault(), out var tenantId) - ? tenantId - : null; - } - - if (prefix.StartsWith("dict:", StringComparison.Ordinal) && !prefix.StartsWith("dict:items:", StringComparison.Ordinal)) - { - var token = prefix.Replace("dict:", string.Empty, StringComparison.Ordinal); - return long.TryParse(token.Split(':', StringSplitOptions.RemoveEmptyEntries).FirstOrDefault(), out var tenantId) - ? tenantId - : null; - } - - return null; - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Caching/MemoryCacheService.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Caching/MemoryCacheService.cs deleted file mode 100644 index ca9c7e0..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Caching/MemoryCacheService.cs +++ /dev/null @@ -1,82 +0,0 @@ -using Microsoft.Extensions.Caching.Memory; -using System.Collections.Concurrent; - -namespace TakeoutSaaS.Infrastructure.Dictionary.Caching; - -/// -/// 本地内存缓存封装。 -/// -public sealed class MemoryCacheService(IMemoryCache cache) -{ - private readonly ConcurrentDictionary _keys = new(StringComparer.Ordinal); - - /// - /// 读取缓存。 - /// - public Task GetAsync(string key, CancellationToken cancellationToken = default) - { - return Task.FromResult(cache.TryGetValue(key, out T? value) ? value : default); - } - - /// - /// 写入缓存。 - /// - public Task SetAsync(string key, T value, TimeSpan ttl, CancellationToken cancellationToken = default) - { - cache.Set(key, value, new MemoryCacheEntryOptions - { - SlidingExpiration = ttl - }); - _keys.TryAdd(key, 0); - return Task.CompletedTask; - } - - /// - /// 删除缓存键。 - /// - public void Remove(string key) - { - cache.Remove(key); - _keys.TryRemove(key, out _); - } - - /// - /// 按前缀删除缓存键。 - /// - public void RemoveByPrefix(string prefix) - => RemoveByPrefixWithCount(prefix); - - /// - /// 按前缀删除缓存键并返回数量。 - /// - public int RemoveByPrefixWithCount(string prefix) - { - if (string.IsNullOrWhiteSpace(prefix)) - { - return 0; - } - - var removed = 0; - foreach (var key in _keys.Keys) - { - if (key.StartsWith(prefix, StringComparison.Ordinal)) - { - Remove(key); - removed += 1; - } - } - - return removed; - } - - /// - /// 清理所有缓存。 - /// - public void Clear() - { - foreach (var key in _keys.Keys) - { - Remove(key); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Caching/RedisCacheService.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Caching/RedisCacheService.cs deleted file mode 100644 index f28ff57..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Caching/RedisCacheService.cs +++ /dev/null @@ -1,79 +0,0 @@ -using Microsoft.Extensions.Caching.Distributed; -using System.Text.Json; -using StackExchange.Redis; - -namespace TakeoutSaaS.Infrastructure.Dictionary.Caching; - -/// -/// Redis 缓存访问封装。 -/// -public sealed class RedisCacheService(IDistributedCache cache, IConnectionMultiplexer? multiplexer = null) -{ - private readonly JsonSerializerOptions _serializerOptions = new(JsonSerializerDefaults.Web); - private readonly IDatabase? _database = multiplexer?.GetDatabase(); - private readonly IConnectionMultiplexer? _multiplexer = multiplexer; - - /// - /// 读取缓存。 - /// - public async Task GetAsync(string key, CancellationToken cancellationToken = default) - { - var payload = await cache.GetAsync(key, cancellationToken); - if (payload == null || payload.Length == 0) - { - return default; - } - - return JsonSerializer.Deserialize(payload, _serializerOptions); - } - - /// - /// 写入缓存。 - /// - public Task SetAsync(string key, T value, TimeSpan ttl, CancellationToken cancellationToken = default) - { - var payload = JsonSerializer.SerializeToUtf8Bytes(value, _serializerOptions); - var options = new DistributedCacheEntryOptions - { - AbsoluteExpirationRelativeToNow = ttl - }; - return cache.SetAsync(key, payload, options, cancellationToken); - } - - /// - /// 删除缓存键。 - /// - public Task RemoveAsync(string key, CancellationToken cancellationToken = default) - => cache.RemoveAsync(key, cancellationToken); - - /// - /// 按前缀删除缓存键。 - /// - public async Task RemoveByPrefixAsync(string prefix, CancellationToken cancellationToken = default) - => await RemoveByPrefixWithCountAsync(prefix, cancellationToken).ConfigureAwait(false); - - /// - /// 按前缀删除缓存键并返回数量。 - /// - public async Task RemoveByPrefixWithCountAsync(string prefix, CancellationToken cancellationToken = default) - { - if (_multiplexer == null || _database == null || string.IsNullOrWhiteSpace(prefix)) - { - return 0; - } - - var pattern = prefix.EndsWith('*') ? prefix : $"{prefix}*"; - long removed = 0; - foreach (var endpoint in _multiplexer.GetEndPoints()) - { - var server = _multiplexer.GetServer(endpoint); - foreach (var key in server.Keys(pattern: pattern)) - { - await _database.KeyDeleteAsync(key).ConfigureAwait(false); - removed += 1; - } - } - - return removed; - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Extensions/DictionaryServiceCollectionExtensions.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Extensions/DictionaryServiceCollectionExtensions.cs deleted file mode 100644 index 1db973a..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Extensions/DictionaryServiceCollectionExtensions.cs +++ /dev/null @@ -1,111 +0,0 @@ -using Microsoft.Extensions.Caching.Distributed; -using Microsoft.Extensions.Caching.StackExchangeRedis; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using StackExchange.Redis; -using TakeoutSaaS.Application.Dictionary.Abstractions; -using TakeoutSaaS.Domain.Dictionary.Repositories; -using TakeoutSaaS.Domain.SystemParameters.Repositories; -using TakeoutSaaS.Infrastructure.Common.Extensions; -using TakeoutSaaS.Infrastructure.Dictionary.Caching; -using TakeoutSaaS.Infrastructure.Dictionary.ImportExport; -using TakeoutSaaS.Infrastructure.Dictionary.Options; -using TakeoutSaaS.Infrastructure.Dictionary.Persistence; -using TakeoutSaaS.Infrastructure.Dictionary.Repositories; -using TakeoutSaaS.Infrastructure.Dictionary.Services; -using TakeoutSaaS.Shared.Abstractions.Constants; - -namespace TakeoutSaaS.Infrastructure.Dictionary.Extensions; - -/// -/// 字典基础设施注册扩展。 -/// -public static class DictionaryServiceCollectionExtensions -{ - /// - /// 注册字典模块基础设施。 - /// - /// 服务集合。 - /// 配置源。 - /// 服务集合。 - /// 缺少数据库配置时抛出。 - public static IServiceCollection AddDictionaryInfrastructure(this IServiceCollection services, IConfiguration configuration) - { - services.AddDatabaseInfrastructure(configuration); - services.AddPostgresDbContext(DatabaseConstants.DictionaryDataSource); - - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - - services.AddMemoryCache(); - - var redisConnection = configuration.GetConnectionString("Redis"); - var hasDistributedCache = services.Any(descriptor => descriptor.ServiceType == typeof(IDistributedCache)); - if (!hasDistributedCache) - { - if (!string.IsNullOrWhiteSpace(redisConnection)) - { - services.AddStackExchangeRedisCache(options => - { - options.Configuration = redisConnection; - }); - } - else - { - services.AddDistributedMemoryCache(); - } - } - - if (!string.IsNullOrWhiteSpace(redisConnection) && !services.Any(descriptor => descriptor.ServiceType == typeof(IConnectionMultiplexer))) - { - services.AddSingleton(_ => ConnectionMultiplexer.Connect(redisConnection)); - } - - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(sp => new RedisCacheService( - sp.GetRequiredService(), - sp.GetService())); - services.AddSingleton(sp => new HybridCacheService( - sp.GetRequiredService(), - sp.GetRequiredService(), - sp.GetService(), - sp.GetService>(), - sp.GetService(), - sp.GetService())); - services.AddSingleton(sp => sp.GetRequiredService()); - - services.AddOptions() - .Bind(configuration.GetSection("Dictionary:Cache")) - .ValidateDataAnnotations(); - - services.AddOptions() - .Bind(configuration.GetSection("CacheWarmup")) - .ValidateDataAnnotations(); - - services.AddHostedService(); - - return services; - } - - /// - /// 确保数据库连接已配置(Database 节或 ConnectionStrings)。 - /// - /// 配置源。 - /// 数据源名称。 - /// 未配置时抛出。 - private static void EnsureDatabaseConnectionConfigured(IConfiguration configuration, string dataSourceName) - { - // 保留兼容接口,当前逻辑在 DatabaseConnectionFactory 中兜底并记录日志。 - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/ImportExport/CsvDictionaryParser.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/ImportExport/CsvDictionaryParser.cs deleted file mode 100644 index ed92bc4..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/ImportExport/CsvDictionaryParser.cs +++ /dev/null @@ -1,91 +0,0 @@ -using CsvHelper; -using CsvHelper.Configuration; -using System.Globalization; -using System.Text; -using TakeoutSaaS.Application.Dictionary.Abstractions; -using TakeoutSaaS.Application.Dictionary.Models; - -namespace TakeoutSaaS.Infrastructure.Dictionary.ImportExport; - -/// -/// CSV 字典导入解析器。 -/// -public sealed class CsvDictionaryParser : ICsvDictionaryParser -{ - private static readonly CsvConfiguration CsvConfiguration = new(CultureInfo.InvariantCulture) - { - HasHeaderRecord = true, - MissingFieldFound = null, - BadDataFound = null, - DetectColumnCountChanges = false, - TrimOptions = TrimOptions.Trim, - PrepareHeaderForMatch = args => args.Header?.Trim().ToLowerInvariant() ?? string.Empty - }; - - /// - public async Task> ParseAsync(Stream stream, CancellationToken cancellationToken = default) - { - ArgumentNullException.ThrowIfNull(stream); - - if (stream.CanSeek) - { - stream.Position = 0; - } - - var rows = new List(); - using var reader = new StreamReader(stream, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false), detectEncodingFromByteOrderMarks: true, leaveOpen: true); - using var csv = new CsvReader(reader, CsvConfiguration); - - if (!await csv.ReadAsync() || !csv.ReadHeader()) - { - return rows; - } - - while (await csv.ReadAsync()) - { - cancellationToken.ThrowIfCancellationRequested(); - - var rowNumber = csv.Context?.Parser?.Row ?? 0; - rows.Add(new DictionaryImportRow - { - RowNumber = rowNumber, - Code = ReadString(csv, "code"), - Key = ReadString(csv, "key"), - Value = ReadString(csv, "value"), - SortOrder = ReadInt(csv, "sortorder"), - IsEnabled = ReadBool(csv, "isenabled"), - Description = ReadString(csv, "description"), - Source = ReadString(csv, "source") - }); - } - - return rows; - } - - private static string? ReadString(CsvReader csv, string name) - { - return csv.TryGetField(name, out string? value) - ? string.IsNullOrWhiteSpace(value) ? null : value - : null; - } - - private static int? ReadInt(CsvReader csv, string name) - { - if (csv.TryGetField(name, out string? value) && int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var number)) - { - return number; - } - - return null; - } - - private static bool? ReadBool(CsvReader csv, string name) - { - if (csv.TryGetField(name, out string? value) && bool.TryParse(value, out var flag)) - { - return flag; - } - - return null; - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/ImportExport/JsonDictionaryParser.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/ImportExport/JsonDictionaryParser.cs deleted file mode 100644 index 855105b..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/ImportExport/JsonDictionaryParser.cs +++ /dev/null @@ -1,131 +0,0 @@ -using System.Text.Json; -using TakeoutSaaS.Application.Dictionary.Abstractions; -using TakeoutSaaS.Application.Dictionary.Models; - -namespace TakeoutSaaS.Infrastructure.Dictionary.ImportExport; - -/// -/// JSON 字典导入解析器。 -/// -public sealed class JsonDictionaryParser : IJsonDictionaryParser -{ - private static readonly JsonDocumentOptions DocumentOptions = new() - { - AllowTrailingCommas = true - }; - - /// - public async Task> ParseAsync(Stream stream, CancellationToken cancellationToken = default) - { - ArgumentNullException.ThrowIfNull(stream); - - if (stream.CanSeek) - { - stream.Position = 0; - } - - using var document = await JsonDocument.ParseAsync(stream, DocumentOptions, cancellationToken); - if (document.RootElement.ValueKind != JsonValueKind.Array) - { - return Array.Empty(); - } - - var rows = new List(); - var index = 0; - - foreach (var element in document.RootElement.EnumerateArray()) - { - cancellationToken.ThrowIfCancellationRequested(); - index++; - - rows.Add(new DictionaryImportRow - { - RowNumber = index, - Code = ReadString(element, "code"), - Key = ReadString(element, "key"), - Value = ReadValue(element, "value"), - SortOrder = ReadInt(element, "sortOrder"), - IsEnabled = ReadBool(element, "isEnabled"), - Description = ReadString(element, "description"), - Source = ReadString(element, "source") - }); - } - - return rows; - } - - private static string? ReadString(JsonElement element, string propertyName) - { - if (!TryGetProperty(element, propertyName, out var value) || value.ValueKind == JsonValueKind.Null) - { - return null; - } - - return value.ValueKind == JsonValueKind.String ? value.GetString() : value.GetRawText(); - } - - private static string? ReadValue(JsonElement element, string propertyName) - { - if (!TryGetProperty(element, propertyName, out var value) || value.ValueKind == JsonValueKind.Null) - { - return null; - } - - return value.ValueKind == JsonValueKind.String ? value.GetString() : value.GetRawText(); - } - - private static int? ReadInt(JsonElement element, string propertyName) - { - if (!TryGetProperty(element, propertyName, out var value)) - { - return null; - } - - if (value.ValueKind == JsonValueKind.Number && value.TryGetInt32(out var number)) - { - return number; - } - - if (value.ValueKind == JsonValueKind.String && int.TryParse(value.GetString(), out var parsed)) - { - return parsed; - } - - return null; - } - - private static bool? ReadBool(JsonElement element, string propertyName) - { - if (!TryGetProperty(element, propertyName, out var value)) - { - return null; - } - - if (value.ValueKind == JsonValueKind.True || value.ValueKind == JsonValueKind.False) - { - return value.GetBoolean(); - } - - if (value.ValueKind == JsonValueKind.String && bool.TryParse(value.GetString(), out var parsed)) - { - return parsed; - } - - return null; - } - - private static bool TryGetProperty(JsonElement element, string propertyName, out JsonElement value) - { - foreach (var property in element.EnumerateObject()) - { - if (string.Equals(property.Name, propertyName, StringComparison.OrdinalIgnoreCase)) - { - value = property.Value; - return true; - } - } - - value = default; - return false; - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Options/DictionaryCacheOptions.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Options/DictionaryCacheOptions.cs deleted file mode 100644 index c5df7a0..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Options/DictionaryCacheOptions.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace TakeoutSaaS.Infrastructure.Dictionary.Options; - -/// -/// 字典缓存配置。 -/// -public sealed class DictionaryCacheOptions -{ - /// - /// 缓存滑动过期时间。 - /// - public TimeSpan SlidingExpiration { get; set; } = TimeSpan.FromMinutes(30); -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Options/DictionaryCacheWarmupOptions.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Options/DictionaryCacheWarmupOptions.cs deleted file mode 100644 index 7c5c2f4..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Options/DictionaryCacheWarmupOptions.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace TakeoutSaaS.Infrastructure.Dictionary.Options; - -/// -/// 字典缓存预热配置。 -/// -public sealed class DictionaryCacheWarmupOptions -{ - /// - /// 预热字典编码列表(最多前 10 个)。 - /// - public string[] DictionaryCodes { get; set; } = Array.Empty(); -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Persistence/DictionaryDbContext.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Persistence/DictionaryDbContext.cs deleted file mode 100644 index 0339ac7..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Persistence/DictionaryDbContext.cs +++ /dev/null @@ -1,267 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; -using TakeoutSaaS.Domain.Dictionary.Entities; -using TakeoutSaaS.Domain.Dictionary.ValueObjects; -using TakeoutSaaS.Domain.SystemParameters.Entities; -using TakeoutSaaS.Infrastructure.Common.Persistence; -using TakeoutSaaS.Shared.Abstractions.Ids; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Infrastructure.Dictionary.Persistence; - -/// -/// 参数字典 DbContext:承载字典与系统参数。 -/// -public sealed class DictionaryDbContext( - DbContextOptions options, - ITenantProvider tenantProvider, - ICurrentUserAccessor? currentUserAccessor = null, - IIdGenerator? idGenerator = null) - : TenantAwareDbContext(options, tenantProvider, currentUserAccessor, idGenerator) -{ - /// - /// 字典分组集合。 - /// - public DbSet DictionaryGroups => Set(); - - /// - /// 字典项集合。 - /// - public DbSet DictionaryItems => Set(); - - /// - /// 租户字典覆盖集合。 - /// - public DbSet TenantDictionaryOverrides => Set(); - - /// - /// 字典导入日志集合。 - /// - public DbSet DictionaryImportLogs => Set(); - - /// - /// 缓存失效日志集合。 - /// - public DbSet CacheInvalidationLogs => Set(); - - /// - /// 字典标签覆盖集合。 - /// - public DbSet DictionaryLabelOverrides => Set(); - - /// - /// 系统参数集合。 - /// - public DbSet SystemParameters => Set(); - - /// - /// 配置实体模型。 - /// - /// 模型构建器。 - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - base.OnModelCreating(modelBuilder); - var provider = Database.ProviderName; - var isSqlite = provider != null && provider.Contains("Sqlite", StringComparison.OrdinalIgnoreCase); - ConfigureGroup(modelBuilder.Entity(), isSqlite); - ConfigureItem(modelBuilder.Entity(), isSqlite); - ConfigureOverride(modelBuilder.Entity()); - ConfigureLabelOverride(modelBuilder.Entity()); - ConfigureImportLog(modelBuilder.Entity()); - ConfigureCacheInvalidationLog(modelBuilder.Entity()); - ConfigureSystemParameter(modelBuilder.Entity()); - ApplyTenantQueryFilters(modelBuilder); - } - - /// - /// 配置字典分组。 - /// - /// 实体构建器。 - private static void ConfigureGroup(EntityTypeBuilder builder, bool isSqlite) - { - builder.ToTable("dictionary_groups"); - builder.HasKey(x => x.Id); - builder.Property(x => x.TenantId).IsRequired(); - builder.Property(x => x.Code) - .HasConversion(code => code.Value, value => new DictionaryCode(value)) - .HasMaxLength(64) - .IsRequired(); - builder.Property(x => x.Name).HasMaxLength(128).IsRequired(); - builder.Property(x => x.Scope).HasConversion().IsRequired(); - builder.Property(x => x.AllowOverride).HasDefaultValue(false); - builder.Property(x => x.Description).HasMaxLength(512); - builder.Property(x => x.IsEnabled).HasDefaultValue(true); - ConfigureAuditableEntity(builder); - ConfigureSoftDeleteEntity(builder); - - var rowVersion = builder.Property(x => x.RowVersion) - .IsConcurrencyToken(); - - if (isSqlite) - { - rowVersion.ValueGeneratedNever(); - rowVersion.HasColumnType("BLOB"); - } - else - { - rowVersion.IsRowVersion().HasColumnType("bytea"); - } - - builder.HasIndex(x => x.TenantId); - builder.HasIndex(x => new { x.TenantId, x.Code }) - .IsUnique() - .HasFilter("\"DeletedAt\" IS NULL"); - builder.HasIndex(x => new { x.TenantId, x.Scope, x.IsEnabled }); - } - - /// - /// 配置字典项。 - /// - /// 实体构建器。 - private static void ConfigureItem(EntityTypeBuilder builder, bool isSqlite) - { - builder.ToTable("dictionary_items"); - builder.HasKey(x => x.Id); - builder.Property(x => x.TenantId).IsRequired(); - builder.Property(x => x.GroupId).IsRequired(); - builder.Property(x => x.Key).HasMaxLength(128).IsRequired(); - builder.Property(x => x.Value).HasColumnType("jsonb").IsRequired(); - builder.Property(x => x.Description).HasMaxLength(512); - builder.Property(x => x.SortOrder).HasDefaultValue(100); - builder.Property(x => x.IsEnabled).HasDefaultValue(true); - ConfigureAuditableEntity(builder); - ConfigureSoftDeleteEntity(builder); - - var rowVersion = builder.Property(x => x.RowVersion) - .IsConcurrencyToken(); - - if (isSqlite) - { - rowVersion.ValueGeneratedNever(); - rowVersion.HasColumnType("BLOB"); - } - else - { - rowVersion.IsRowVersion().HasColumnType("bytea"); - } - - builder.HasOne(x => x.Group) - .WithMany(g => g.Items) - .HasForeignKey(x => x.GroupId) - .OnDelete(DeleteBehavior.Cascade); - - builder.HasIndex(x => x.TenantId); - builder.HasIndex(x => new { x.TenantId, x.GroupId, x.Key }) - .IsUnique() - .HasFilter("\"DeletedAt\" IS NULL"); - builder.HasIndex(x => new { x.GroupId, x.IsEnabled, x.SortOrder }); - } - - /// - /// 配置租户字典覆盖。 - /// - /// 实体构建器。 - private static void ConfigureOverride(EntityTypeBuilder builder) - { - builder.ToTable("tenant_dictionary_overrides"); - builder.HasKey(x => new { x.TenantId, x.SystemDictionaryGroupId }); - builder.Property(x => x.OverrideEnabled).HasDefaultValue(false); - builder.Property(x => x.HiddenSystemItemIds).HasColumnType("bigint[]"); - builder.Property(x => x.CustomSortOrder).HasColumnType("jsonb"); - ConfigureAuditableEntity(builder); - ConfigureSoftDeleteEntity(builder); - - builder.HasIndex(x => x.HiddenSystemItemIds).HasMethod("gin"); - } - - /// - /// 配置字典导入日志。 - /// - /// 实体构建器。 - private static void ConfigureImportLog(EntityTypeBuilder builder) - { - builder.ToTable("dictionary_import_logs"); - builder.HasKey(x => x.Id); - builder.Property(x => x.OperatorId).IsRequired(); - builder.Property(x => x.DictionaryGroupCode).HasMaxLength(64).IsRequired(); - builder.Property(x => x.FileName).HasMaxLength(256).IsRequired(); - builder.Property(x => x.Format).HasMaxLength(16).IsRequired(); - builder.Property(x => x.ErrorDetails).HasColumnType("jsonb"); - builder.Property(x => x.ProcessedAt).IsRequired(); - builder.Property(x => x.Duration).HasColumnType("interval"); - ConfigureAuditableEntity(builder); - ConfigureSoftDeleteEntity(builder); - - builder.HasIndex(x => new { x.TenantId, x.ProcessedAt }); - } - - /// - /// 配置缓存失效日志。 - /// - /// 实体构建器。 - private static void ConfigureCacheInvalidationLog(EntityTypeBuilder builder) - { - builder.ToTable("dictionary_cache_invalidation_logs"); - builder.HasKey(x => x.Id); - builder.Property(x => x.DictionaryCode).HasMaxLength(64).IsRequired(); - builder.Property(x => x.Scope).HasConversion().IsRequired(); - builder.Property(x => x.Operation).HasConversion().IsRequired(); - builder.Property(x => x.Timestamp).IsRequired(); - ConfigureAuditableEntity(builder); - ConfigureSoftDeleteEntity(builder); - - builder.HasIndex(x => new { x.TenantId, x.Timestamp }); - } - - /// - /// 配置系统参数。 - /// - /// 实体构建器。 - private static void ConfigureSystemParameter(EntityTypeBuilder builder) - { - builder.ToTable("system_parameters"); - builder.HasKey(x => x.Id); - builder.Property(x => x.TenantId).IsRequired(); - builder.Property(x => x.Key).HasMaxLength(128).IsRequired(); - builder.Property(x => x.Value).HasColumnType("text").IsRequired(); - builder.Property(x => x.Description).HasMaxLength(512); - builder.Property(x => x.SortOrder).HasDefaultValue(100); - builder.Property(x => x.IsEnabled).HasDefaultValue(true); - ConfigureAuditableEntity(builder); - ConfigureSoftDeleteEntity(builder); - - builder.HasIndex(x => x.TenantId); - builder.HasIndex(x => new { x.TenantId, x.Key }).IsUnique(); - } - - /// - /// 配置字典标签覆盖。 - /// - /// 实体构建器。 - private static void ConfigureLabelOverride(EntityTypeBuilder builder) - { - builder.ToTable("dictionary_label_overrides", t => t.HasComment("字典标签覆盖配置。")); - builder.HasKey(x => x.Id); - builder.Property(x => x.Id).HasComment("实体唯一标识。"); - builder.Property(x => x.TenantId).IsRequired().HasComment("所属租户 ID(覆盖目标租户)。"); - builder.Property(x => x.DictionaryItemId).IsRequired().HasComment("被覆盖的字典项 ID。"); - builder.Property(x => x.OriginalValue).HasColumnType("jsonb").IsRequired().HasComment("原始显示值(JSON 格式,多语言)。"); - builder.Property(x => x.OverrideValue).HasColumnType("jsonb").IsRequired().HasComment("覆盖后的显示值(JSON 格式,多语言)。"); - builder.Property(x => x.OverrideType).HasConversion().IsRequired().HasComment("覆盖类型。"); - builder.Property(x => x.Reason).HasMaxLength(512).HasComment("覆盖原因/备注。"); - ConfigureAuditableEntity(builder); - ConfigureSoftDeleteEntity(builder); - - builder.HasOne(x => x.DictionaryItem) - .WithMany() - .HasForeignKey(x => x.DictionaryItemId) - .OnDelete(DeleteBehavior.Cascade); - - builder.HasIndex(x => x.TenantId); - builder.HasIndex(x => new { x.TenantId, x.DictionaryItemId }) - .IsUnique() - .HasFilter("\"DeletedAt\" IS NULL"); - builder.HasIndex(x => new { x.TenantId, x.OverrideType }); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Persistence/DictionaryDesignTimeDbContextFactory.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Persistence/DictionaryDesignTimeDbContextFactory.cs deleted file mode 100644 index 774c649..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Persistence/DictionaryDesignTimeDbContextFactory.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Infrastructure.Common.Persistence.DesignTime; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Infrastructure.Dictionary.Persistence; - -/// -/// 设计时 DictionaryDbContext 工厂。 -/// -internal sealed class DictionaryDesignTimeDbContextFactory - : DesignTimeDbContextFactoryBase -{ - /// - /// 初始化字典库设计时上下文工厂。 - /// - public DictionaryDesignTimeDbContextFactory() - : base(DatabaseConstants.DictionaryDataSource, "TAKEOUTSAAS_DICTIONARY_CONNECTION") - { - } - // 创建设计时上下文 - /// - /// 创建设计时的 DictionaryDbContext。 - /// - /// 上下文配置。 - /// 租户提供器。 - /// 当前用户访问器。 - /// DictionaryDbContext 实例。 - protected override DictionaryDbContext CreateContext( - DbContextOptions options, - ITenantProvider tenantProvider, - ICurrentUserAccessor currentUserAccessor) - => new(options, tenantProvider, currentUserAccessor); -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/CacheInvalidationLogRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/CacheInvalidationLogRepository.cs deleted file mode 100644 index f0dcbad..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/CacheInvalidationLogRepository.cs +++ /dev/null @@ -1,59 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Dictionary.Entities; -using TakeoutSaaS.Domain.Dictionary.Repositories; -using TakeoutSaaS.Infrastructure.Dictionary.Persistence; - -namespace TakeoutSaaS.Infrastructure.Dictionary.Repositories; - -/// -/// 缓存失效日志仓储实现。 -/// -public sealed class CacheInvalidationLogRepository(DictionaryDbContext context) : ICacheInvalidationLogRepository -{ - /// - /// 新增失效日志。 - /// - public Task AddAsync(CacheInvalidationLog log, CancellationToken cancellationToken = default) - { - context.CacheInvalidationLogs.Add(log); - return Task.CompletedTask; - } - - /// - /// 分页查询失效日志。 - /// - public async Task<(IReadOnlyList Items, int TotalCount)> GetPagedAsync( - int page, - int pageSize, - DateTime? startDate, - DateTime? endDate, - CancellationToken cancellationToken = default) - { - var query = context.CacheInvalidationLogs.AsNoTracking(); - - if (startDate.HasValue) - { - query = query.Where(log => log.Timestamp >= startDate.Value); - } - - if (endDate.HasValue) - { - query = query.Where(log => log.Timestamp <= endDate.Value); - } - - var total = await query.CountAsync(cancellationToken); - var items = await query - .OrderByDescending(log => log.Timestamp) - .Skip((page - 1) * pageSize) - .Take(pageSize) - .ToListAsync(cancellationToken); - - return (items, total); - } - - /// - /// 保存变更。 - /// - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - => context.SaveChangesAsync(cancellationToken); -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/DictionaryGroupRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/DictionaryGroupRepository.cs deleted file mode 100644 index c73b37b..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/DictionaryGroupRepository.cs +++ /dev/null @@ -1,173 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Dictionary.Entities; -using TakeoutSaaS.Domain.Dictionary.Enums; -using TakeoutSaaS.Domain.Dictionary.Repositories; -using TakeoutSaaS.Domain.Dictionary.ValueObjects; -using TakeoutSaaS.Infrastructure.Dictionary.Persistence; - -namespace TakeoutSaaS.Infrastructure.Dictionary.Repositories; - -/// -/// 字典分组仓储实现。 -/// -public sealed class DictionaryGroupRepository(DictionaryDbContext context) : IDictionaryGroupRepository -{ - private static readonly Func> GetByCodeQuery = - EF.CompileAsyncQuery((DictionaryDbContext db, long tenantId, DictionaryCode code) => - db.DictionaryGroups - .AsNoTracking() - .FirstOrDefault(group => group.TenantId == tenantId && group.DeletedAt == null && group.Code == code)); - - /// - /// 按 ID 获取字典分组。 - /// - public Task GetByIdAsync(long groupId, CancellationToken cancellationToken = default) - { - return context.DictionaryGroups - .AsNoTracking() - .FirstOrDefaultAsync(group => group.Id == groupId && group.DeletedAt == null, cancellationToken); - } - - /// - /// 按编码获取字典分组。 - /// - public Task GetByCodeAsync(long tenantId, DictionaryCode code, CancellationToken cancellationToken = default) - { - _ = cancellationToken; - return GetByCodeQuery(context, tenantId, code); - } - - /// - /// 分页获取字典分组。 - /// - public async Task> GetPagedAsync( - long tenantId, - DictionaryScope? scope, - string? keyword, - bool? isEnabled, - int page, - int pageSize, - string? sortBy, - bool sortDescending, - CancellationToken cancellationToken = default) - { - var query = BuildQuery(tenantId, scope, keyword, isEnabled); - - var skip = Math.Max(page - 1, 0) * Math.Max(pageSize, 1); - query = ApplyOrdering(query, sortBy, sortDescending); - - return await query - .Skip(skip) - .Take(pageSize) - .ToListAsync(cancellationToken); - } - - /// - /// 获取满足条件的分组数量。 - /// - public Task CountAsync( - long tenantId, - DictionaryScope? scope, - string? keyword, - bool? isEnabled, - CancellationToken cancellationToken = default) - { - return BuildQuery(tenantId, scope, keyword, isEnabled) - .CountAsync(cancellationToken); - } - - /// - /// 批量获取字典分组。 - /// - public async Task> GetByIdsAsync(IEnumerable groupIds, CancellationToken cancellationToken = default) - { - var ids = groupIds?.Distinct().ToArray() ?? Array.Empty(); - if (ids.Length == 0) - { - return Array.Empty(); - } - - return await context.DictionaryGroups - .AsNoTracking() - .Where(group => ids.Contains(group.Id) && group.DeletedAt == null) - .ToListAsync(cancellationToken); - } - - private static IQueryable ApplyOrdering(IQueryable query, string? sortBy, bool sortDescending) - { - var normalized = sortBy?.Trim().ToLowerInvariant(); - return normalized switch - { - "name" => sortDescending ? query.OrderByDescending(group => group.Name) : query.OrderBy(group => group.Name), - "createdat" => sortDescending ? query.OrderByDescending(group => group.CreatedAt) : query.OrderBy(group => group.CreatedAt), - "updatedat" => sortDescending ? query.OrderByDescending(group => group.UpdatedAt) : query.OrderBy(group => group.UpdatedAt), - _ => sortDescending ? query.OrderByDescending(group => group.Code) : query.OrderBy(group => group.Code) - }; - } - - /// - /// 新增分组。 - /// - public Task AddAsync(DictionaryGroup group, CancellationToken cancellationToken = default) - { - context.DictionaryGroups.Add(group); - return Task.CompletedTask; - } - - /// - /// 更新分组。 - /// - public Task UpdateAsync(DictionaryGroup group, CancellationToken cancellationToken = default) - { - context.DictionaryGroups.Update(group); - return Task.CompletedTask; - } - - /// - /// 删除分组。 - /// - public Task RemoveAsync(DictionaryGroup group, CancellationToken cancellationToken = default) - { - context.DictionaryGroups.Remove(group); - return Task.CompletedTask; - } - - /// - /// 持久化更改。 - /// - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - => context.SaveChangesAsync(cancellationToken); - - private IQueryable BuildQuery(long tenantId, DictionaryScope? scope, string? keyword, bool? isEnabled) - { - var query = context.DictionaryGroups - .AsNoTracking() - .Where(group => group.TenantId == tenantId && group.DeletedAt == null); - - if (scope.HasValue) - { - query = query.Where(group => group.Scope == scope.Value); - } - - if (!string.IsNullOrWhiteSpace(keyword)) - { - var trimmed = keyword.Trim(); - if (DictionaryCode.IsValid(trimmed)) - { - var code = new DictionaryCode(trimmed); - query = query.Where(group => group.Code == code || group.Name.Contains(trimmed)); - } - else - { - query = query.Where(group => group.Name.Contains(trimmed)); - } - } - - if (isEnabled.HasValue) - { - query = query.Where(group => group.IsEnabled == isEnabled.Value); - } - - return query; - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/DictionaryImportLogRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/DictionaryImportLogRepository.cs deleted file mode 100644 index 39cc005..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/DictionaryImportLogRepository.cs +++ /dev/null @@ -1,26 +0,0 @@ -using TakeoutSaaS.Domain.Dictionary.Entities; -using TakeoutSaaS.Domain.Dictionary.Repositories; -using TakeoutSaaS.Infrastructure.Dictionary.Persistence; - -namespace TakeoutSaaS.Infrastructure.Dictionary.Repositories; - -/// -/// 字典导入日志仓储实现。 -/// -public sealed class DictionaryImportLogRepository(DictionaryDbContext context) : IDictionaryImportLogRepository -{ - /// - /// 新增导入日志。 - /// - public Task AddAsync(DictionaryImportLog log, CancellationToken cancellationToken = default) - { - context.DictionaryImportLogs.Add(log); - return Task.CompletedTask; - } - - /// - /// 持久化更改。 - /// - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - => context.SaveChangesAsync(cancellationToken); -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/DictionaryItemRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/DictionaryItemRepository.cs deleted file mode 100644 index ed869bb..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/DictionaryItemRepository.cs +++ /dev/null @@ -1,147 +0,0 @@ -using System.Security.Cryptography; -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Dictionary.Entities; -using TakeoutSaaS.Domain.Dictionary.Repositories; -using TakeoutSaaS.Infrastructure.Dictionary.Persistence; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Infrastructure.Dictionary.Repositories; - -/// -/// 字典项仓储实现。 -/// -public sealed class DictionaryItemRepository(DictionaryDbContext context, ITenantContextAccessor tenantContextAccessor) : IDictionaryItemRepository -{ - private static readonly Func> GetByGroupQuery = - EF.CompileQuery((DictionaryDbContext db, long tenantId, long groupId) => - (IEnumerable)db.DictionaryItems - .AsNoTracking() - .Where(item => item.GroupId == groupId && item.TenantId == tenantId && item.DeletedAt == null) - .OrderBy(item => item.SortOrder)); - - /// - /// 根据 ID 获取字典项。 - /// - public Task GetByIdAsync(long itemId, CancellationToken cancellationToken = default) - { - return context.DictionaryItems - .AsNoTracking() - .FirstOrDefaultAsync(item => item.Id == itemId && item.DeletedAt == null, cancellationToken); - } - - /// - /// 获取分组下字典项列表。 - /// - public Task> GetByGroupIdAsync( - long tenantId, - long groupId, - CancellationToken cancellationToken = default) - { - _ = cancellationToken; - return Task.FromResult>( - GetByGroupQuery(context, tenantId, groupId).ToList()); - } - - /// - /// 获取系统与租户合并的字典项列表。 - /// - public async Task> GetMergedItemsAsync( - long tenantId, - long systemGroupId, - bool includeOverrides, - CancellationToken cancellationToken = default) - { - DictionaryGroup? systemGroup; - List systemItems; - using (tenantContextAccessor.EnterTenantScope(0, "dictionary")) - { - systemGroup = await context.DictionaryGroups - .AsNoTracking() - .FirstOrDefaultAsync(group => group.Id == systemGroupId && group.DeletedAt == null, cancellationToken); - if (systemGroup == null) - { - return Array.Empty(); - } - - systemItems = await context.DictionaryItems - .AsNoTracking() - .Where(item => item.GroupId == systemGroupId && item.DeletedAt == null) - .OrderBy(item => item.SortOrder) - .ToListAsync(cancellationToken); - } - - var result = new List(systemItems); - - if (!includeOverrides || tenantId == 0) - { - return result; - } - - var tenantGroup = await context.DictionaryGroups - .AsNoTracking() - .FirstOrDefaultAsync(group => - group.TenantId == tenantId && - group.DeletedAt == null && - group.Code == systemGroup.Code, - cancellationToken); - - if (tenantGroup == null) - { - return result; - } - - var tenantItems = await context.DictionaryItems - .AsNoTracking() - .Where(item => item.GroupId == tenantGroup.Id && item.TenantId == tenantId && item.DeletedAt == null) - .OrderBy(item => item.SortOrder) - .ToListAsync(cancellationToken); - - result.AddRange(tenantItems); - return result; - } - - /// - /// 新增字典项。 - /// - public Task AddAsync(DictionaryItem item, CancellationToken cancellationToken = default) - { - context.DictionaryItems.Add(item); - return Task.CompletedTask; - } - - /// - /// 更新字典项。 - /// - public Task UpdateAsync(DictionaryItem item, CancellationToken cancellationToken = default) - { - var entry = context.Entry(item); - if (entry.State == EntityState.Detached) - { - context.DictionaryItems.Attach(item); - entry = context.Entry(item); - } - - entry.State = EntityState.Modified; - var originalVersion = item.RowVersion; - var nextVersion = RandomNumberGenerator.GetBytes(16); - entry.Property(x => x.RowVersion).OriginalValue = originalVersion; - entry.Property(x => x.RowVersion).CurrentValue = nextVersion; - item.RowVersion = nextVersion; - return Task.CompletedTask; - } - - /// - /// 删除字典项。 - /// - public Task RemoveAsync(DictionaryItem item, CancellationToken cancellationToken = default) - { - context.DictionaryItems.Remove(item); - return Task.CompletedTask; - } - - /// - /// 持久化更改。 - /// - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - => context.SaveChangesAsync(cancellationToken); -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/DictionaryLabelOverrideRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/DictionaryLabelOverrideRepository.cs deleted file mode 100644 index 8dc3b8f..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/DictionaryLabelOverrideRepository.cs +++ /dev/null @@ -1,111 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Dictionary.Entities; -using TakeoutSaaS.Domain.Dictionary.Enums; -using TakeoutSaaS.Domain.Dictionary.Repositories; -using TakeoutSaaS.Infrastructure.Dictionary.Persistence; - -namespace TakeoutSaaS.Infrastructure.Dictionary.Repositories; - -/// -/// 字典标签覆盖仓储实现。 -/// -public sealed class DictionaryLabelOverrideRepository(DictionaryDbContext context) : IDictionaryLabelOverrideRepository -{ - /// - /// 根据 ID 获取覆盖配置。 - /// - public Task GetByIdAsync(long id, CancellationToken cancellationToken = default) - { - return context.DictionaryLabelOverrides - .Include(x => x.DictionaryItem) - .FirstOrDefaultAsync(x => x.Id == id && x.DeletedAt == null, cancellationToken); - } - - /// - /// 获取指定字典项的覆盖配置。 - /// - public Task GetByItemIdAsync(long tenantId, long dictionaryItemId, CancellationToken cancellationToken = default) - { - return context.DictionaryLabelOverrides - .FirstOrDefaultAsync(x => - x.TenantId == tenantId && - x.DictionaryItemId == dictionaryItemId && - x.DeletedAt == null, - cancellationToken); - } - - /// - /// 获取租户的所有覆盖配置。 - /// - public async Task> ListByTenantAsync( - long tenantId, - OverrideType? overrideType = null, - CancellationToken cancellationToken = default) - { - var query = context.DictionaryLabelOverrides - .AsNoTracking() - .Include(x => x.DictionaryItem) - .Where(x => x.TenantId == tenantId && x.DeletedAt == null); - - if (overrideType.HasValue) - { - query = query.Where(x => x.OverrideType == overrideType.Value); - } - - return await query.OrderByDescending(x => x.CreatedAt).ToListAsync(cancellationToken); - } - - /// - /// 批量获取多个字典项的覆盖配置。 - /// - public async Task> GetByItemIdsAsync( - long tenantId, - IEnumerable dictionaryItemIds, - CancellationToken cancellationToken = default) - { - var ids = dictionaryItemIds.ToArray(); - if (ids.Length == 0) return Array.Empty(); - - return await context.DictionaryLabelOverrides - .AsNoTracking() - .Where(x => - x.TenantId == tenantId && - ids.Contains(x.DictionaryItemId) && - x.DeletedAt == null) - .ToListAsync(cancellationToken); - } - - /// - /// 新增覆盖配置。 - /// - public Task AddAsync(DictionaryLabelOverride entity, CancellationToken cancellationToken = default) - { - context.DictionaryLabelOverrides.Add(entity); - return Task.CompletedTask; - } - - /// - /// 更新覆盖配置。 - /// - public Task UpdateAsync(DictionaryLabelOverride entity, CancellationToken cancellationToken = default) - { - context.DictionaryLabelOverrides.Update(entity); - return Task.CompletedTask; - } - - /// - /// 删除覆盖配置。 - /// - public Task DeleteAsync(DictionaryLabelOverride entity, CancellationToken cancellationToken = default) - { - entity.DeletedAt = DateTime.UtcNow; - context.DictionaryLabelOverrides.Update(entity); - return Task.CompletedTask; - } - - /// - /// 持久化更改。 - /// - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - => context.SaveChangesAsync(cancellationToken); -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/EfDictionaryRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/EfDictionaryRepository.cs deleted file mode 100644 index 0d2d6d2..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/EfDictionaryRepository.cs +++ /dev/null @@ -1,200 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Dictionary.Entities; -using TakeoutSaaS.Domain.Dictionary.Enums; -using TakeoutSaaS.Domain.Dictionary.ValueObjects; -using TakeoutSaaS.Domain.Dictionary.Repositories; -using TakeoutSaaS.Infrastructure.Dictionary.Persistence; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Infrastructure.Dictionary.Repositories; - -/// -/// EF Core 字典仓储实现。 -/// -public sealed class EfDictionaryRepository(DictionaryDbContext context, ITenantContextAccessor tenantContextAccessor) : IDictionaryRepository -{ - /// - /// 根据分组 ID 查询分组。 - /// - /// 分组 ID。 - /// 取消标记。 - /// 匹配分组或 null。 - public Task FindGroupByIdAsync(long id, CancellationToken cancellationToken = default) - => context.DictionaryGroups.FirstOrDefaultAsync(group => group.Id == id, cancellationToken); - - /// - /// 根据分组编码查询分组。 - /// - /// 分组编码。 - /// 取消标记。 - /// 匹配分组或 null。 - public Task FindGroupByCodeAsync(string code, CancellationToken cancellationToken = default) - => context.DictionaryGroups.FirstOrDefaultAsync(group => group.Code == new DictionaryCode(code), cancellationToken); - - /// - /// 搜索分组列表。 - /// - /// 字典作用域。 - /// 取消标记。 - /// 分组列表。 - public async Task> SearchGroupsAsync(DictionaryScope? scope, CancellationToken cancellationToken = default) - { - // 1. 构建分组查询 - var query = context.DictionaryGroups.AsNoTracking(); - if (scope.HasValue) - { - // 2. 按作用域过滤 - query = query.Where(group => group.Scope == scope.Value); - } - - // 3. 排序返回 - return await query - .OrderBy(group => group.Code) - .ToListAsync(cancellationToken); - } - - /// - /// 新增分组。 - /// - /// 分组实体。 - /// 取消标记。 - /// 异步任务。 - public Task AddGroupAsync(DictionaryGroup group, CancellationToken cancellationToken = default) - { - // 1. 添加分组 - context.DictionaryGroups.Add(group); - // 2. 返回完成任务 - return Task.CompletedTask; - } - - /// - /// 删除分组。 - /// - /// 分组实体。 - /// 取消标记。 - /// 异步任务。 - public Task RemoveGroupAsync(DictionaryGroup group, CancellationToken cancellationToken = default) - { - // 1. 移除分组 - context.DictionaryGroups.Remove(group); - // 2. 返回完成任务 - return Task.CompletedTask; - } - - /// - /// 根据条目 ID 查询字典项。 - /// - /// 条目 ID。 - /// 取消标记。 - /// 匹配条目或 null。 - public Task FindItemByIdAsync(long id, CancellationToken cancellationToken = default) - => context.DictionaryItems.FirstOrDefaultAsync(item => item.Id == id, cancellationToken); - - /// - /// 获取指定分组下的条目列表。 - /// - /// 分组 ID。 - /// 取消标记。 - /// 条目列表。 - public async Task> GetItemsByGroupIdAsync(long groupId, CancellationToken cancellationToken = default) - { - // 1. 过滤分组 - return await context.DictionaryItems - .AsNoTracking() - .Where(item => item.GroupId == groupId) - .OrderBy(item => item.SortOrder) - .ToListAsync(cancellationToken); - } - - /// - /// 新增字典项。 - /// - /// 字典项。 - /// 取消标记。 - /// 异步任务。 - public Task AddItemAsync(DictionaryItem item, CancellationToken cancellationToken = default) - { - // 1. 添加条目 - context.DictionaryItems.Add(item); - // 2. 返回完成任务 - return Task.CompletedTask; - } - - /// - /// 删除字典项。 - /// - /// 字典项。 - /// 取消标记。 - /// 异步任务。 - public Task RemoveItemAsync(DictionaryItem item, CancellationToken cancellationToken = default) - { - // 1. 移除条目 - context.DictionaryItems.Remove(item); - // 2. 返回完成任务 - return Task.CompletedTask; - } - - /// - /// 持久化变更。 - /// - /// 取消标记。 - /// 保存任务。 - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - => context.SaveChangesAsync(cancellationToken); - - /// - /// 根据编码集合获取条目列表,可包含系统级条目。 - /// - /// 分组编码集合。 - /// 租户 ID。 - /// 是否包含系统级。 - /// 取消标记。 - /// 条目列表。 - public async Task> GetItemsByCodesAsync(IEnumerable codes, long tenantId, bool includeSystem, CancellationToken cancellationToken = default) - { - // 1. 规范化编码 - var normalizedCodes = codes - .Where(code => !string.IsNullOrWhiteSpace(code)) - .Select(code => new DictionaryCode(code)) - .Distinct() - .ToArray(); - - if (normalizedCodes.Length == 0) - { - return Array.Empty(); - } - - // 2. 查询当前租户条目 - var tenantItems = await context.DictionaryItems - .AsNoTracking() - .Include(item => item.Group) - .Where(item => item.TenantId == tenantId && normalizedCodes.Contains(item.Group!.Code) && item.DeletedAt == null) - .OrderBy(item => item.SortOrder) - .ToListAsync(cancellationToken); - - if (!includeSystem) - { - return tenantItems; - } - - // 3. (空行后) 查询系统级条目(TenantId=0) - List systemItems; - using (tenantContextAccessor.EnterTenantScope(0, "dictionary")) - { - systemItems = await context.DictionaryItems - .AsNoTracking() - .Include(item => item.Group) - .Where(item => item.TenantId == 0 && normalizedCodes.Contains(item.Group!.Code) && item.DeletedAt == null) - .OrderBy(item => item.SortOrder) - .ToListAsync(cancellationToken); - } - - // 4. (空行后) 合并返回(系统优先) - if (systemItems.Count == 0) - { - return tenantItems; - } - - return [.. systemItems, .. tenantItems]; - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/EfSystemParameterRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/EfSystemParameterRepository.cs deleted file mode 100644 index d7e515c..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/EfSystemParameterRepository.cs +++ /dev/null @@ -1,79 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.SystemParameters.Entities; -using TakeoutSaaS.Domain.SystemParameters.Repositories; -using TakeoutSaaS.Infrastructure.Dictionary.Persistence; - -namespace TakeoutSaaS.Infrastructure.Dictionary.Repositories; - -/// -/// 系统参数 EF Core 仓储实现。 -/// -public sealed class EfSystemParameterRepository(DictionaryDbContext context) : ISystemParameterRepository -{ - /// - public Task FindByIdAsync(long id, CancellationToken cancellationToken = default) - { - return context.SystemParameters - .AsNoTracking() - .FirstOrDefaultAsync(x => x.Id == id, cancellationToken); - } - - /// - public Task FindByKeyAsync(string key, CancellationToken cancellationToken = default) - { - var normalizedKey = key.Trim(); - return context.SystemParameters - .AsNoTracking() - .FirstOrDefaultAsync(x => x.Key == normalizedKey, cancellationToken); - } - - /// - public async Task> SearchAsync(string? keyword, bool? isEnabled, CancellationToken cancellationToken = default) - { - var query = context.SystemParameters.AsNoTracking(); - - if (!string.IsNullOrWhiteSpace(keyword)) - { - var normalized = keyword.Trim(); - query = query.Where(x => x.Key.Contains(normalized) || (x.Description != null && x.Description.Contains(normalized))); - } - - if (isEnabled.HasValue) - { - query = query.Where(x => x.IsEnabled == isEnabled.Value); - } - - var parameters = await query - .OrderBy(x => x.SortOrder) - .ThenBy(x => x.Key) - .ToListAsync(cancellationToken); - - return parameters; - } - - /// - public Task AddAsync(SystemParameter parameter, CancellationToken cancellationToken = default) - { - return context.SystemParameters.AddAsync(parameter, cancellationToken).AsTask(); - } - - /// - public Task RemoveAsync(SystemParameter parameter, CancellationToken cancellationToken = default) - { - context.SystemParameters.Remove(parameter); - return Task.CompletedTask; - } - - /// - public Task UpdateAsync(SystemParameter parameter, CancellationToken cancellationToken = default) - { - context.SystemParameters.Update(parameter); - return Task.CompletedTask; - } - - /// - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - { - return context.SaveChangesAsync(cancellationToken); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/TenantDictionaryOverrideRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/TenantDictionaryOverrideRepository.cs deleted file mode 100644 index 71aec4c..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/TenantDictionaryOverrideRepository.cs +++ /dev/null @@ -1,60 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Dictionary.Entities; -using TakeoutSaaS.Domain.Dictionary.Repositories; -using TakeoutSaaS.Infrastructure.Dictionary.Persistence; - -namespace TakeoutSaaS.Infrastructure.Dictionary.Repositories; - -/// -/// 租户字典覆盖仓储实现。 -/// -public sealed class TenantDictionaryOverrideRepository(DictionaryDbContext context) : ITenantDictionaryOverrideRepository -{ - /// - /// 获取租户覆盖配置。 - /// - public Task GetAsync(long tenantId, long systemGroupId, CancellationToken cancellationToken = default) - { - return context.TenantDictionaryOverrides - .FirstOrDefaultAsync(config => - config.TenantId == tenantId && - config.SystemDictionaryGroupId == systemGroupId && - config.DeletedAt == null, - cancellationToken); - } - - /// - /// 获取租户全部覆盖配置。 - /// - public async Task> ListAsync(long tenantId, CancellationToken cancellationToken = default) - { - return await context.TenantDictionaryOverrides - .AsNoTracking() - .Where(config => config.TenantId == tenantId && config.DeletedAt == null) - .ToListAsync(cancellationToken); - } - - /// - /// 新增覆盖配置。 - /// - public Task AddAsync(TenantDictionaryOverride overrideConfig, CancellationToken cancellationToken = default) - { - context.TenantDictionaryOverrides.Add(overrideConfig); - return Task.CompletedTask; - } - - /// - /// 更新覆盖配置。 - /// - public Task UpdateAsync(TenantDictionaryOverride overrideConfig, CancellationToken cancellationToken = default) - { - context.TenantDictionaryOverrides.Update(overrideConfig); - return Task.CompletedTask; - } - - /// - /// 持久化更改。 - /// - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - => context.SaveChangesAsync(cancellationToken); -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Services/DistributedDictionaryCache.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Services/DistributedDictionaryCache.cs deleted file mode 100644 index 800af5e..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Services/DistributedDictionaryCache.cs +++ /dev/null @@ -1,75 +0,0 @@ -using Microsoft.Extensions.Caching.Distributed; -using Microsoft.Extensions.Options; -using System.Text.Json; -using TakeoutSaaS.Application.Dictionary.Abstractions; -using TakeoutSaaS.Application.Dictionary.Models; -using TakeoutSaaS.Infrastructure.Dictionary.Options; - -namespace TakeoutSaaS.Infrastructure.Dictionary.Services; - -/// -/// 基于 IDistributedCache 的字典缓存实现。 -/// -public sealed class DistributedDictionaryCache(IDistributedCache cache, IOptions options) : IDictionaryCache -{ - private readonly DictionaryCacheOptions _options = options.Value; - private readonly JsonSerializerOptions _serializerOptions = new(JsonSerializerDefaults.Web); - - /// - /// 读取指定租户与编码的字典缓存。 - /// - /// 租户 ID。 - /// 字典编码。 - /// 取消标记。 - /// 字典项集合或 null。 - public async Task?> GetAsync(long tenantId, string code, CancellationToken cancellationToken = default) - { - // 1. 拼装缓存键 - var cacheKey = BuildKey(tenantId, code); - var payload = await cache.GetAsync(cacheKey, cancellationToken); - if (payload == null || payload.Length == 0) - { - return null; - } - - // 2. 反序列化 - return JsonSerializer.Deserialize>(payload, _serializerOptions); - } - - /// - /// 设置指定租户与编码的字典缓存。 - /// - /// 租户 ID。 - /// 字典编码。 - /// 字典项集合。 - /// 取消标记。 - /// 异步任务。 - public Task SetAsync(long tenantId, string code, IReadOnlyList items, CancellationToken cancellationToken = default) - { - // 1. 序列化并写入缓存 - var cacheKey = BuildKey(tenantId, code); - var payload = JsonSerializer.SerializeToUtf8Bytes(items, _serializerOptions); - var options = new DistributedCacheEntryOptions - { - SlidingExpiration = _options.SlidingExpiration - }; - return cache.SetAsync(cacheKey, payload, options, cancellationToken); - } - - /// - /// 移除指定租户与编码的缓存。 - /// - /// 租户 ID。 - /// 字典编码。 - /// 取消标记。 - /// 异步任务。 - public Task RemoveAsync(long tenantId, string code, CancellationToken cancellationToken = default) - { - // 1. 删除缓存键 - var cacheKey = BuildKey(tenantId, code); - return cache.RemoveAsync(cacheKey, cancellationToken); - } - - private static string BuildKey(long tenantId, string code) - => $"dictionary:{tenantId}:{code.ToLowerInvariant()}"; -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Extensions/JwtAuthenticationExtensions.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Extensions/JwtAuthenticationExtensions.cs deleted file mode 100644 index b346321..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Extensions/JwtAuthenticationExtensions.cs +++ /dev/null @@ -1,54 +0,0 @@ -using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.IdentityModel.Tokens; -using System.IdentityModel.Tokens.Jwt; -using System.Security.Claims; -using System.Text; -using TakeoutSaaS.Infrastructure.Identity.Options; - -namespace TakeoutSaaS.Infrastructure.Identity.Extensions; - -/// -/// JWT 认证扩展 -/// -public static class JwtAuthenticationExtensions -{ - /// - /// 配置 JWT Bearer 认证 - /// - public static IServiceCollection AddJwtAuthentication(this IServiceCollection services, IConfiguration configuration) - { - var jwtOptions = configuration.GetSection("Identity:Jwt").Get() - ?? throw new InvalidOperationException("缺少 Identity:Jwt 配置"); - - JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); - JwtSecurityTokenHandler.DefaultOutboundClaimTypeMap.Clear(); - - services - .AddAuthentication(options => - { - options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; - options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; - }) - .AddJwtBearer(options => - { - options.RequireHttpsMetadata = false; - options.TokenValidationParameters = new TokenValidationParameters - { - ValidateIssuer = true, - ValidIssuer = jwtOptions.Issuer, - ValidateAudience = true, - ValidAudience = jwtOptions.Audience, - ValidateIssuerSigningKey = true, - IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtOptions.Secret)), - ValidateLifetime = true, - ClockSkew = TimeSpan.FromMinutes(1), - NameClaimType = ClaimTypes.NameIdentifier, - RoleClaimType = ClaimTypes.Role - }; - }); - - return services; - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Extensions/ServiceCollectionExtensions.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Extensions/ServiceCollectionExtensions.cs deleted file mode 100644 index 217f916..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Extensions/ServiceCollectionExtensions.cs +++ /dev/null @@ -1,119 +0,0 @@ -using Microsoft.AspNetCore.Identity; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using TakeoutSaaS.Application.Identity.Abstractions; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Infrastructure.Common.Extensions; -using TakeoutSaaS.Infrastructure.Identity.Options; -using TakeoutSaaS.Infrastructure.Identity.Persistence; -using TakeoutSaaS.Infrastructure.Identity.Repositories; -using TakeoutSaaS.Infrastructure.Identity.Services; -using TakeoutSaaS.Infrastructure.Logs.Publishers; -using TakeoutSaaS.Shared.Abstractions.Constants; -using DomainIdentityUser = TakeoutSaaS.Domain.Identity.Entities.IdentityUser; - -namespace TakeoutSaaS.Infrastructure.Identity.Extensions; - -/// -/// 身份认证基础设施注入。 -/// -public static class ServiceCollectionExtensions -{ - /// - /// 注册身份认证基础设施(数据库、Redis、JWT、限流等)。 - /// - /// 服务集合。 - /// 配置源。 - /// 是否启用小程序相关依赖(如微信登录)。 - /// 是否启用后台账号初始化。 - /// 服务集合。 - /// 配置缺失时抛出。 - public static IServiceCollection AddIdentityInfrastructure( - this IServiceCollection services, - IConfiguration configuration, - bool enableMiniFeatures = false, - bool enableAdminSeed = false) - { - services.AddDatabaseInfrastructure(configuration); - services.AddPostgresDbContext(DatabaseConstants.IdentityDataSource); - - var redisConnection = configuration.GetConnectionString("Redis"); - if (string.IsNullOrWhiteSpace(redisConnection)) - { - throw new InvalidOperationException("缺少 Redis 连接字符串配置。"); - } - - services.AddStackExchangeRedisCache(options => - { - options.Configuration = redisConnection; - }); - - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped, PasswordHasher>(); - services.AddScoped(); - - services.AddOptions() - .Bind(configuration.GetSection("Identity:Jwt")) - .ValidateDataAnnotations() - .ValidateOnStart(); - - services.AddOptions() - .Bind(configuration.GetSection("Identity:LoginRateLimit")) - .ValidateDataAnnotations() - .ValidateOnStart(); - - services.AddOptions() - .Bind(configuration.GetSection("Identity:RefreshTokenStore")); - - services.AddOptions() - .Bind(configuration.GetSection("Identity:AdminPasswordReset")); - - if (enableMiniFeatures) - { - services.AddOptions() - .Bind(configuration.GetSection("Identity:WeChatMini")) - .ValidateDataAnnotations() - .ValidateOnStart(); - - services.AddHttpClient(client => - { - client.BaseAddress = new Uri("https://api.weixin.qq.com/"); - client.Timeout = TimeSpan.FromSeconds(10); - }); - } - - if (enableAdminSeed) - { - services.AddOptions() - .Bind(configuration.GetSection("Identity:AdminSeed")) - .ValidateDataAnnotations() - .ValidateOnStart(); - - services.AddHostedService(); - } - - return services; - } - - /// - /// 确保数据库连接已配置(Database 节或 ConnectionStrings)。 - /// - /// 配置源。 - /// 数据源名称。 - /// 未配置时抛出。 - private static void EnsureDatabaseConnectionConfigured(IConfiguration configuration, string dataSourceName) - { - // 保留兼容接口,当前逻辑在 DatabaseConnectionFactory 中兜底并记录日志。 - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Options/AdminPasswordResetOptions.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Options/AdminPasswordResetOptions.cs deleted file mode 100644 index 1a958a6..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Options/AdminPasswordResetOptions.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace TakeoutSaaS.Infrastructure.Identity.Options; - -/// -/// 管理后台重置密码链接令牌配置。 -/// -public sealed class AdminPasswordResetOptions -{ - /// - /// Redis Key 前缀。 - /// - public string Prefix { get; init; } = "identity:admin:pwdreset:"; -} - diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Options/AdminSeedOptions.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Options/AdminSeedOptions.cs deleted file mode 100644 index eab01eb..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Options/AdminSeedOptions.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Infrastructure.Identity.Options; - -/// -/// 管理后台初始账号配置。 -/// -public sealed class AdminSeedOptions -{ - /// - /// 是否启用后台账号与权限种子。 - /// - public bool Enabled { get; set; } = true; - - /// - /// 初始用户列表。 - /// - public List Users { get; set; } = new(); - - /// - /// 角色模板种子列表。 - /// - public List RoleTemplates { get; set; } = new(); -} - -/// -/// 种子用户配置:用于初始化管理后台账号。 -/// -public sealed class SeedUserOptions -{ - /// - /// 登录账号。 - /// - [Required] - public string Account { get; set; } = string.Empty; - - /// - /// 登录密码(明文,将在初始化时进行哈希处理)。 - /// - [Required] - public string Password { get; set; } = string.Empty; - - /// - /// 展示名称。 - /// - [Required] - public string DisplayName { get; set; } = string.Empty; - - /// - /// 所属租户 ID。 - /// - public long TenantId { get; set; } - - /// - /// 所属商户 ID(租户管理员为空)。 - /// - public long? MerchantId { get; set; } - - /// - /// 角色集合。 - /// - public string[] Roles { get; set; } = Array.Empty(); - - /// - /// 权限集合。 - /// - public string[] Permissions { get; set; } = Array.Empty(); -} - -/// -/// 角色模板种子配置。 -/// -public sealed class RoleTemplateSeedOptions -{ - /// - /// 模板编码。 - /// - [Required] - public string TemplateCode { get; set; } = string.Empty; - - /// - /// 模板名称。 - /// - [Required] - public string Name { get; set; } = string.Empty; - - /// - /// 模板描述。 - /// - public string? Description { get; set; } - - /// - /// 是否启用。 - /// - public bool IsActive { get; set; } = true; - - /// - /// 权限编码集合。 - /// - public string[] Permissions { get; set; } = Array.Empty(); -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Options/JwtOptions.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Options/JwtOptions.cs deleted file mode 100644 index 18aed1d..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Options/JwtOptions.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Infrastructure.Identity.Options; - -/// -/// JWT 配置选项。 -/// -public sealed class JwtOptions -{ - /// - /// 令牌颁发者(Issuer)。 - /// - [Required] - public string Issuer { get; set; } = string.Empty; - - /// - /// 令牌受众(Audience)。 - /// - [Required] - public string Audience { get; set; } = string.Empty; - - /// - /// JWT 签名密钥(至少 32 个字符)。 - /// - [Required] - [MinLength(32)] - public string Secret { get; set; } = string.Empty; - - /// - /// 访问令牌过期时间(分钟),范围:5-1440。 - /// - [Range(5, 1440)] - public int AccessTokenExpirationMinutes { get; set; } = 60; - - /// - /// 刷新令牌过期时间(分钟),范围:60-20160(14天)。 - /// - [Range(60, 1440 * 14)] - public int RefreshTokenExpirationMinutes { get; set; } = 60 * 24 * 7; -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Options/LoginRateLimitOptions.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Options/LoginRateLimitOptions.cs deleted file mode 100644 index d9f7a42..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Options/LoginRateLimitOptions.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Infrastructure.Identity.Options; - -/// -/// 登录限流配置选项。 -/// -public sealed class LoginRateLimitOptions -{ - /// - /// 时间窗口(秒),范围:1-3600。 - /// - [Range(1, 3600)] - public int WindowSeconds { get; set; } = 60; - - /// - /// 时间窗口内允许的最大尝试次数,范围:1-100。 - /// - [Range(1, 100)] - public int MaxAttempts { get; set; } = 5; -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Options/RefreshTokenStoreOptions.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Options/RefreshTokenStoreOptions.cs deleted file mode 100644 index fcbf6e8..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Options/RefreshTokenStoreOptions.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace TakeoutSaaS.Infrastructure.Identity.Options; - -/// -/// 刷新令牌存储配置选项。 -/// -public sealed class RefreshTokenStoreOptions -{ - /// - /// Redis 键前缀,用于存储刷新令牌。 - /// - public string Prefix { get; set; } = "identity:refresh:"; -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Options/WeChatMiniOptions.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Options/WeChatMiniOptions.cs deleted file mode 100644 index 0dee3be..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Options/WeChatMiniOptions.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Infrastructure.Identity.Options; - -/// -/// 微信小程序配置选项。 -/// -public sealed class WeChatMiniOptions -{ - /// - /// 微信小程序 AppId。 - /// - [Required] - public string AppId { get; set; } = string.Empty; - - /// - /// 微信小程序 AppSecret。 - /// - [Required] - public string Secret { get; set; } = string.Empty; -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfIdentityUserRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfIdentityUserRepository.cs deleted file mode 100644 index dc05a67..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfIdentityUserRepository.cs +++ /dev/null @@ -1,373 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Identity.Entities; -using TakeoutSaaS.Domain.Identity.Repositories; - -namespace TakeoutSaaS.Infrastructure.Identity.Persistence; - -/// -/// EF Core 后台用户仓储实现。 -/// -public sealed class EfIdentityUserRepository(IdentityDbContext dbContext) : IIdentityUserRepository -{ - /// - /// 根据租户与账号获取后台用户。 - /// - /// 租户 ID。 - /// 账号。 - /// 取消标记。 - /// 后台用户或 null。 - public Task FindByAccountAsync(long tenantId, string account, CancellationToken cancellationToken = default) - { - // 1. 标准化账号 - var normalized = account.Trim(); - - // 2. 查询用户(强制租户隔离) - return dbContext.IdentityUsers - .AsNoTracking() - .FirstOrDefaultAsync(x => x.TenantId == tenantId && x.Account == normalized, cancellationToken); - } - - /// - /// 判断账号是否存在。 - /// - /// 账号。 - /// 取消标记。 - /// 存在返回 true。 - public Task ExistsByAccountAsync(string account, CancellationToken cancellationToken = default) - { - // 1. 标准化账号 - var normalized = account.Trim(); - // 2. 查询是否存在 - return dbContext.IdentityUsers.AnyAsync(x => x.Account == normalized, cancellationToken); - } - - /// - /// 判断账号是否存在(租户内,可排除指定用户)。 - /// - /// 租户 ID。 - /// 账号。 - /// 排除的用户 ID。 - /// 取消标记。 - /// 存在返回 true。 - public async Task ExistsByAccountAsync(long tenantId, string account, long? excludeUserId = null, CancellationToken cancellationToken = default) - { - // 1. 标准化账号 - var normalized = account.Trim(); - - // 2. 构建查询(包含已删除数据,但不放开租户过滤) - using var disableSoftDeleteScope = dbContext.DisableSoftDeleteFilter(); - var query = dbContext.IdentityUsers.AsNoTracking() - .Where(x => x.TenantId == tenantId && x.Account == normalized); - - if (excludeUserId.HasValue) - { - query = query.Where(x => x.Id != excludeUserId.Value); - } - - // 3. 返回是否存在 - return await query.AnyAsync(cancellationToken); - } - - /// - /// 判断手机号是否存在(租户内,可排除指定用户)。 - /// - /// 租户 ID。 - /// 手机号。 - /// 排除的用户 ID。 - /// 取消标记。 - /// 存在返回 true。 - public async Task ExistsByPhoneAsync(long tenantId, string phone, long? excludeUserId = null, CancellationToken cancellationToken = default) - { - // 1. 标准化手机号 - var normalized = phone.Trim(); - - // 2. 构建查询(包含已删除数据,但不放开租户过滤) - using var disableSoftDeleteScope = dbContext.DisableSoftDeleteFilter(); - var query = dbContext.IdentityUsers.AsNoTracking() - .Where(x => x.TenantId == tenantId && x.Phone == normalized); - - if (excludeUserId.HasValue) - { - query = query.Where(x => x.Id != excludeUserId.Value); - } - - // 3. 返回是否存在 - return await query.AnyAsync(cancellationToken); - } - - /// - /// 判断邮箱是否存在(租户内,可排除指定用户)。 - /// - /// 租户 ID。 - /// 邮箱。 - /// 排除的用户 ID。 - /// 取消标记。 - /// 存在返回 true。 - public async Task ExistsByEmailAsync(long tenantId, string email, long? excludeUserId = null, CancellationToken cancellationToken = default) - { - // 1. 标准化邮箱 - var normalized = email.Trim(); - - // 2. 构建查询(包含已删除数据,但不放开租户过滤) - using var disableSoftDeleteScope = dbContext.DisableSoftDeleteFilter(); - var query = dbContext.IdentityUsers.AsNoTracking() - .Where(x => x.TenantId == tenantId && x.Email == normalized); - - if (excludeUserId.HasValue) - { - query = query.Where(x => x.Id != excludeUserId.Value); - } - - // 3. 返回是否存在 - return await query.AnyAsync(cancellationToken); - } - - /// - /// 根据 ID 获取后台用户。 - /// - /// 用户 ID。 - /// 取消标记。 - /// 后台用户或 null。 - public Task FindByIdAsync(long userId, CancellationToken cancellationToken = default) - => dbContext.IdentityUsers.AsNoTracking().FirstOrDefaultAsync(x => x.Id == userId, cancellationToken); - - /// - /// 根据 ID 获取后台用户(用于更新,返回可跟踪实体)。 - /// - /// 用户 ID。 - /// 取消标记。 - /// 后台用户或 null。 - public Task GetForUpdateAsync(long userId, CancellationToken cancellationToken = default) - => dbContext.IdentityUsers.FirstOrDefaultAsync(x => x.Id == userId, cancellationToken); - - /// - /// 根据 ID 获取后台用户(用于更新,包含已删除数据)。 - /// - /// 租户 ID。 - /// 用户 ID。 - /// 取消标记。 - /// 后台用户或 null。 - public async Task GetForUpdateIncludingDeletedAsync( - long tenantId, - long userId, - CancellationToken cancellationToken = default) - { - // 1. 构建查询(包含已删除数据,但强制租户隔离) - using var disableSoftDeleteScope = dbContext.DisableSoftDeleteFilter(); - return await dbContext.IdentityUsers - .Where(x => x.TenantId == tenantId) - .FirstOrDefaultAsync(x => x.Id == userId, cancellationToken); - } - - /// - /// 按租户与关键字搜索后台用户(只读)。 - /// - /// 租户 ID。 - /// 关键字(账号/名称)。 - /// 取消标记。 - /// 后台用户列表。 - public async Task> SearchAsync(long tenantId, string? keyword, CancellationToken cancellationToken = default) - { - // 1. 构建基础查询 - var query = dbContext.IdentityUsers - .AsNoTracking() - .Where(x => x.TenantId == tenantId); - - // 2. 关键字过滤 - if (!string.IsNullOrWhiteSpace(keyword)) - { - var normalized = keyword.Trim(); - query = query.Where(x => x.Account.Contains(normalized) || x.DisplayName.Contains(normalized)); - } - - // 3. 返回列表 - return await query.ToListAsync(cancellationToken); - } - - /// - /// 分页查询后台用户列表。 - /// - /// 查询过滤条件。 - /// 取消标记。 - /// 分页结果。 - public async Task<(IReadOnlyList Items, int Total)> SearchPagedAsync( - IdentityUserSearchFilter filter, - CancellationToken cancellationToken = default) - { - if (!filter.TenantId.HasValue || filter.TenantId.Value <= 0) - { - throw new InvalidOperationException("TenantId 不能为空且必须大于 0"); - } - - var tenantId = filter.TenantId.Value; - - using var disableSoftDeleteScope = filter.IncludeDeleted ? dbContext.DisableSoftDeleteFilter() : null; - - // 1. 构建基础查询 - var query = dbContext.IdentityUsers.AsNoTracking(); - - // 2. 租户过滤(强制) - query = query.Where(x => x.TenantId == tenantId); - - // 3. 关键字筛选 - if (!string.IsNullOrWhiteSpace(filter.Keyword)) - { - var normalized = filter.Keyword.Trim(); - var likeValue = $"%{normalized}%"; - query = query.Where(x => - EF.Functions.ILike(x.Account, likeValue) - || EF.Functions.ILike(x.DisplayName, likeValue) - || (x.Phone != null && EF.Functions.ILike(x.Phone, likeValue)) - || (x.Email != null && EF.Functions.ILike(x.Email, likeValue))); - } - - // 4. 状态过滤 - if (filter.Status.HasValue) - { - query = query.Where(x => x.Status == filter.Status.Value); - } - - // 5. 角色过滤 - if (filter.RoleId.HasValue) - { - var roleId = filter.RoleId.Value; - var userRoles = dbContext.UserRoles.AsNoTracking(); - - userRoles = userRoles.Where(x => x.TenantId == tenantId); - - query = query.Where(user => userRoles.Any(role => role.UserId == user.Id && role.RoleId == roleId)); - } - - // 6. 时间范围过滤 - if (filter.CreatedAtFrom.HasValue) - { - query = query.Where(x => x.CreatedAt >= filter.CreatedAtFrom.Value); - } - - if (filter.CreatedAtTo.HasValue) - { - query = query.Where(x => x.CreatedAt <= filter.CreatedAtTo.Value); - } - - if (filter.LastLoginFrom.HasValue) - { - query = query.Where(x => x.LastLoginAt >= filter.LastLoginFrom.Value); - } - - if (filter.LastLoginTo.HasValue) - { - query = query.Where(x => x.LastLoginAt <= filter.LastLoginTo.Value); - } - - // 7. 排序 - var sorted = filter.SortBy?.ToLowerInvariant() switch - { - "account" => filter.SortDescending - ? query.OrderByDescending(x => x.Account) - : query.OrderBy(x => x.Account), - "displayname" => filter.SortDescending - ? query.OrderByDescending(x => x.DisplayName) - : query.OrderBy(x => x.DisplayName), - "status" => filter.SortDescending - ? query.OrderByDescending(x => x.Status) - : query.OrderBy(x => x.Status), - "lastloginat" => filter.SortDescending - ? query.OrderByDescending(x => x.LastLoginAt) - : query.OrderBy(x => x.LastLoginAt), - _ => filter.SortDescending - ? query.OrderByDescending(x => x.CreatedAt) - : query.OrderBy(x => x.CreatedAt) - }; - - // 8. 分页 - var page = filter.Page <= 0 ? 1 : filter.Page; - var pageSize = filter.PageSize <= 0 ? 20 : filter.PageSize; - var total = await sorted.CountAsync(cancellationToken); - var items = await sorted - .Skip((page - 1) * pageSize) - .Take(pageSize) - .ToListAsync(cancellationToken); - - return (items, total); - } - - /// - /// 根据 ID 集合批量获取后台用户(只读)。 - /// - /// 租户 ID。 - /// 用户 ID 集合。 - /// 取消标记。 - /// 后台用户列表。 - public async Task> GetByIdsAsync(long tenantId, IEnumerable userIds, CancellationToken cancellationToken = default) - { - return await dbContext.IdentityUsers.AsNoTracking() - .Where(x => x.TenantId == tenantId && userIds.Contains(x.Id)) - .ToListAsync(cancellationToken); - } - - /// - /// 批量获取后台用户(可用于更新,支持包含已删除数据)。 - /// - /// 租户 ID。 - /// 用户 ID 集合。 - /// 是否包含已删除数据。 - /// 取消标记。 - /// 后台用户列表。 - public async Task> GetForUpdateByIdsAsync( - long tenantId, - IEnumerable userIds, - bool includeDeleted, - CancellationToken cancellationToken = default) - { - // 1. 构建基础查询 - var ids = userIds.Distinct().ToArray(); - if (ids.Length == 0) - { - return Array.Empty(); - } - - var query = dbContext.IdentityUsers.Where(x => ids.Contains(x.Id)); - using var disableSoftDeleteScope = includeDeleted ? dbContext.DisableSoftDeleteFilter() : null; - - query = query.Where(x => x.TenantId == tenantId); - - // 2. 返回列表 - return await query.ToListAsync(cancellationToken); - } - - /// - /// 新增后台用户。 - /// - /// 后台用户实体。 - /// 取消标记。 - /// 异步任务。 - public Task AddAsync(IdentityUser user, CancellationToken cancellationToken = default) - { - // 1. 添加实体 - dbContext.IdentityUsers.Add(user); - // 2. 返回完成任务 - return Task.CompletedTask; - } - - /// - /// 删除后台用户(软删除)。 - /// - /// 后台用户实体。 - /// 取消标记。 - /// 异步任务。 - public Task RemoveAsync(IdentityUser user, CancellationToken cancellationToken = default) - { - // 1. 标记删除 - dbContext.IdentityUsers.Remove(user); - // 2. 返回完成任务 - return Task.CompletedTask; - } - - /// - /// 持久化仓储变更。 - /// - /// 取消标记。 - /// 保存任务。 - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - => dbContext.SaveChangesAsync(cancellationToken); -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfMiniUserRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfMiniUserRepository.cs deleted file mode 100644 index efb45a4..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfMiniUserRepository.cs +++ /dev/null @@ -1,70 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Identity.Entities; -using TakeoutSaaS.Domain.Identity.Repositories; - -namespace TakeoutSaaS.Infrastructure.Identity.Persistence; - -/// -/// EF Core 小程序用户仓储实现。 -/// -public sealed class EfMiniUserRepository(IdentityDbContext dbContext) : IMiniUserRepository -{ - /// - /// 根据 OpenId 获取小程序用户。 - /// - /// 微信 OpenId。 - /// 取消标记。 - /// 匹配的小程序用户或 null。 - public Task FindByOpenIdAsync(string openId, CancellationToken cancellationToken = default) - => dbContext.MiniUsers.AsNoTracking().FirstOrDefaultAsync(x => x.OpenId == openId, cancellationToken); - - /// - /// 根据用户 ID 获取小程序用户。 - /// - /// 用户 ID。 - /// 取消标记。 - /// 匹配的小程序用户或 null。 - public Task FindByIdAsync(long id, CancellationToken cancellationToken = default) - => dbContext.MiniUsers.AsNoTracking().FirstOrDefaultAsync(x => x.Id == id, cancellationToken); - - /// - /// 创建或更新小程序用户信息。 - /// - /// 微信 OpenId。 - /// 微信 UnionId。 - /// 昵称。 - /// 头像地址。 - /// 租户 ID。 - /// 取消标记。 - /// 创建或更新后的小程序用户。 - public async Task CreateOrUpdateAsync(string openId, string? unionId, string? nickname, string? avatar, long tenantId, CancellationToken cancellationToken = default) - { - // 1. 查询现有用户 - var user = await dbContext.MiniUsers.FirstOrDefaultAsync(x => x.OpenId == openId, cancellationToken); - if (user == null) - { - // 2. 未找到则创建 - user = new MiniUser - { - Id = 0, - OpenId = openId, - UnionId = unionId, - Nickname = nickname ?? "小程序用户", - Avatar = avatar, - TenantId = tenantId - }; - dbContext.MiniUsers.Add(user); - } - else - { - // 3. 已存在则更新可变字段 - user.UnionId = unionId ?? user.UnionId; - user.Nickname = nickname ?? user.Nickname; - user.Avatar = avatar ?? user.Avatar; - } - - // 4. 保存更改 - await dbContext.SaveChangesAsync(cancellationToken); - return user; - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfPermissionRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfPermissionRepository.cs deleted file mode 100644 index 0d07f47..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfPermissionRepository.cs +++ /dev/null @@ -1,162 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Identity.Entities; -using TakeoutSaaS.Domain.Identity.Repositories; - -namespace TakeoutSaaS.Infrastructure.Identity.Persistence; - -/// -/// EF 权限仓储。 -/// -/// -/// 权限是系统级数据,使用 IgnoreQueryFilters 忽略多租户过滤。 -/// -public sealed class EfPermissionRepository(IdentityDbContext dbContext) : IPermissionRepository -{ - /// - /// 根据权限 ID 获取权限。 - /// - /// 权限 ID。 - /// 租户 ID(保留参数,实际不使用)。 - /// 取消标记。 - /// 权限实体或 null。 - public Task FindByIdAsync(long permissionId, long tenantId, CancellationToken cancellationToken = default) - => dbContext.Permissions - .IgnoreQueryFilters() - .AsNoTracking() - .FirstOrDefaultAsync(x => x.Id == permissionId && x.DeletedAt == null, cancellationToken); - - /// - /// 根据权限编码获取权限。 - /// - /// 权限编码。 - /// 租户 ID(保留参数,实际不使用)。 - /// 取消标记。 - /// 权限实体或 null。 - public Task FindByCodeAsync(string code, long tenantId, CancellationToken cancellationToken = default) - => dbContext.Permissions - .IgnoreQueryFilters() - .AsNoTracking() - .FirstOrDefaultAsync(x => x.Code == code && x.DeletedAt == null, cancellationToken); - - /// - /// 根据权限编码集合批量获取权限。 - /// - /// 租户 ID(保留参数,实际不使用)。 - /// 权限编码集合。 - /// 取消标记。 - /// 权限列表。 - public Task> GetByCodesAsync(long tenantId, IEnumerable codes, CancellationToken cancellationToken = default) - { - // 1. 规范化编码集合 - var normalizedCodes = codes - .Where(code => !string.IsNullOrWhiteSpace(code)) - .Select(code => code.Trim()) - .Distinct() - .ToArray(); - - // 2. 读取权限(忽略租户过滤) - return dbContext.Permissions - .IgnoreQueryFilters() - .AsNoTracking() - .Where(x => x.DeletedAt == null && normalizedCodes.Contains(x.Code)) - .ToListAsync(cancellationToken) - .ContinueWith(t => (IReadOnlyList)t.Result, cancellationToken); - } - - /// - /// 根据权限 ID 集合批量获取权限。 - /// - /// 租户 ID(保留参数,实际不使用)。 - /// 权限 ID 集合。 - /// 取消标记。 - /// 权限列表。 - public Task> GetByIdsAsync(long tenantId, IEnumerable permissionIds, CancellationToken cancellationToken = default) - => dbContext.Permissions - .IgnoreQueryFilters() - .AsNoTracking() - .Where(x => x.DeletedAt == null && permissionIds.Contains(x.Id)) - .ToListAsync(cancellationToken) - .ContinueWith(t => (IReadOnlyList)t.Result, cancellationToken); - - /// - /// 按关键字搜索权限。 - /// - /// 租户 ID(保留参数,实际不使用)。 - /// 搜索关键字。 - /// 取消标记。 - /// 权限列表。 - public Task> SearchAsync(long tenantId, string? keyword, CancellationToken cancellationToken = default) - { - // 1. 构建基础查询(忽略租户过滤) - var query = dbContext.Permissions - .IgnoreQueryFilters() - .AsNoTracking() - .Where(x => x.DeletedAt == null); - if (!string.IsNullOrWhiteSpace(keyword)) - { - // 2. 追加关键字过滤 - var normalized = keyword.Trim(); - query = query.Where(x => x.Name.Contains(normalized) || x.Code.Contains(normalized)); - } - - // 3. 返回列表 - return query.ToListAsync(cancellationToken) - .ContinueWith(t => (IReadOnlyList)t.Result, cancellationToken); - } - - /// - /// 新增权限。 - /// - /// 权限实体。 - /// 取消标记。 - /// 异步任务。 - public Task AddAsync(Permission permission, CancellationToken cancellationToken = default) - { - // 1. 添加实体 - dbContext.Permissions.Add(permission); - // 2. 返回完成任务 - return Task.CompletedTask; - } - - /// - /// 更新权限。 - /// - /// 权限实体。 - /// 取消标记。 - /// 异步任务。 - public Task UpdateAsync(Permission permission, CancellationToken cancellationToken = default) - { - // 1. 标记实体更新 - dbContext.Permissions.Update(permission); - // 2. 返回完成任务 - return Task.CompletedTask; - } - - /// - /// 删除指定权限。 - /// - /// 权限 ID。 - /// 租户 ID(保留参数,实际不使用)。 - /// 取消标记。 - /// 异步任务。 - public async Task DeleteAsync(long permissionId, long tenantId, CancellationToken cancellationToken = default) - { - // 1. 查询目标权限 - var entity = await dbContext.Permissions - .IgnoreQueryFilters() - .FirstOrDefaultAsync(x => x.Id == permissionId, cancellationToken); - if (entity != null) - { - // 2. 删除实体 - dbContext.Permissions.Remove(entity); - } - } - - /// - /// 保存仓储变更。 - /// - /// 取消标记。 - /// 保存任务。 - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - => dbContext.SaveChangesAsync(cancellationToken); -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfRolePermissionRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfRolePermissionRepository.cs deleted file mode 100644 index 7367c64..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfRolePermissionRepository.cs +++ /dev/null @@ -1,92 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Identity.Entities; -using TakeoutSaaS.Domain.Identity.Repositories; - -namespace TakeoutSaaS.Infrastructure.Identity.Persistence; - -/// -/// EF 角色-权限仓储。 -/// -public sealed class EfRolePermissionRepository(IdentityDbContext dbContext) : IRolePermissionRepository -{ - /// - /// 根据角色 ID 集合获取角色权限映射。 - /// - /// 租户 ID。 - /// 角色 ID 集合。 - /// 取消标记。 - /// 角色权限映射列表。 - public async Task> GetByRoleIdsAsync(long tenantId, IEnumerable roleIds, CancellationToken cancellationToken = default) - { - // 1. 查询角色权限映射 - var mappings = await dbContext.RolePermissions - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.DeletedAt == null && roleIds.Contains(x.RoleId)) - .ToListAsync(cancellationToken); - - // 2. (空行后) 返回只读列表 - return mappings; - } - - /// - /// 批量新增角色权限。 - /// - /// 角色权限集合。 - /// 取消标记。 - /// 异步任务。 - public async Task AddRangeAsync(IEnumerable rolePermissions, CancellationToken cancellationToken = default) - { - // 1. 转为数组便于计数 - var toAdd = rolePermissions as RolePermission[] ?? rolePermissions.ToArray(); - if (toAdd.Length == 0) - { - return; - } - - // 2. 批量插入 - await dbContext.RolePermissions.AddRangeAsync(toAdd, cancellationToken); - } - - /// - /// 替换指定角色的权限集合。 - /// - /// 租户 ID。 - /// 角色 ID。 - /// 权限 ID 集合。 - /// 取消标记。 - /// 异步任务。 - public async Task ReplaceRolePermissionsAsync(long tenantId, long roleId, IEnumerable permissionIds, CancellationToken cancellationToken = default) - { - // 1. 使用执行策略保证可靠性 - var strategy = dbContext.Database.CreateExecutionStrategy(); - await strategy.ExecuteAsync(async () => - { - await using var trx = await dbContext.Database.BeginTransactionAsync(cancellationToken); - - // 1. 删除旧记录(原生 SQL,避免跟踪干扰) - await dbContext.Database.ExecuteSqlRawAsync( - "DELETE FROM \"role_permissions\" WHERE \"TenantId\" = {0} AND \"RoleId\" = {1};", - parameters: new object[] { tenantId, roleId }, - cancellationToken: cancellationToken); - - // 2. 插入新记录(防重复) - foreach (var permissionId in permissionIds.Distinct()) - { - await dbContext.Database.ExecuteSqlRawAsync( - "INSERT INTO \"role_permissions\" (\"TenantId\",\"RoleId\",\"PermissionId\",\"CreatedAt\",\"CreatedBy\",\"UpdatedAt\",\"UpdatedBy\",\"DeletedAt\",\"DeletedBy\") VALUES ({0},{1},{2},NOW(),NULL,NULL,NULL,NULL,NULL) ON CONFLICT DO NOTHING;", - parameters: new object[] { tenantId, roleId, permissionId }, - cancellationToken: cancellationToken); - } - - await trx.CommitAsync(cancellationToken); - }); - } - - /// - /// 保存仓储变更。 - /// - /// 取消标记。 - /// 保存任务。 - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - => dbContext.SaveChangesAsync(cancellationToken); -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfRoleRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfRoleRepository.cs deleted file mode 100644 index 16127ea..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfRoleRepository.cs +++ /dev/null @@ -1,136 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Identity.Entities; -using TakeoutSaaS.Domain.Identity.Repositories; - -namespace TakeoutSaaS.Infrastructure.Identity.Persistence; - -/// -/// EF 角色仓储。 -/// -public sealed class EfRoleRepository(IdentityDbContext dbContext) : IRoleRepository -{ - /// - /// 根据角色 ID 获取角色。 - /// - /// 角色 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 角色实体或 null。 - public Task FindByIdAsync(long roleId, long tenantId, CancellationToken cancellationToken = default) - => dbContext.Roles - .AsNoTracking() - .FirstOrDefaultAsync(x => x.Id == roleId && x.TenantId == tenantId && x.DeletedAt == null, cancellationToken); - - /// - /// 根据角色编码获取角色。 - /// - /// 角色编码。 - /// 租户 ID。 - /// 取消标记。 - /// 角色实体或 null。 - public Task FindByCodeAsync(string code, long tenantId, CancellationToken cancellationToken = default) - => dbContext.Roles - .AsNoTracking() - .FirstOrDefaultAsync(x => x.Code == code && x.TenantId == tenantId && x.DeletedAt == null, cancellationToken); - - /// - /// 根据角色 ID 集合获取角色列表。 - /// - /// 租户 ID。 - /// 角色 ID 集合。 - /// 取消标记。 - /// 角色列表。 - public async Task> GetByIdsAsync(long tenantId, IEnumerable roleIds, CancellationToken cancellationToken = default) - { - // 1. 查询角色列表 - var roles = await dbContext.Roles - .AsNoTracking() - .Where(x => x.TenantId == tenantId && roleIds.Contains(x.Id) && x.DeletedAt == null) - .ToListAsync(cancellationToken); - - // 2. (空行后) 返回只读列表 - return roles; - } - - /// - /// 按关键字搜索角色。 - /// - /// 租户 ID。 - /// 搜索关键字。 - /// 取消标记。 - /// 角色列表。 - public async Task> SearchAsync(long tenantId, string? keyword, CancellationToken cancellationToken = default) - { - // 1. 构建基础查询 - var query = dbContext.Roles - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.DeletedAt == null); - if (!string.IsNullOrWhiteSpace(keyword)) - { - // 2. 追加关键字过滤 - var normalized = keyword.Trim(); - query = query.Where(x => x.Name.Contains(normalized) || x.Code.Contains(normalized)); - } - - // 3. 返回列表 - var roles = await query.ToListAsync(cancellationToken); - - // 4. (空行后) 返回只读列表 - return roles; - } - - /// - /// 新增角色。 - /// - /// 角色实体。 - /// 取消标记。 - /// 异步任务。 - public Task AddAsync(Role role, CancellationToken cancellationToken = default) - { - // 1. 添加实体 - dbContext.Roles.Add(role); - // 2. 返回完成任务 - return Task.CompletedTask; - } - - /// - /// 更新角色。 - /// - /// 角色实体。 - /// 取消标记。 - /// 异步任务。 - public Task UpdateAsync(Role role, CancellationToken cancellationToken = default) - { - // 1. 标记更新 - dbContext.Roles.Update(role); - // 2. 返回完成任务 - return Task.CompletedTask; - } - - /// - /// 软删除角色。 - /// - /// 角色 ID。 - /// 租户 ID。 - /// 取消标记。 - /// 异步任务。 - public async Task DeleteAsync(long roleId, long tenantId, CancellationToken cancellationToken = default) - { - // 1. 查询目标角色 - var entity = await dbContext.Roles.FirstOrDefaultAsync(x => x.Id == roleId && x.TenantId == tenantId, cancellationToken); - if (entity != null) - { - // 2. 标记删除时间 - entity.DeletedAt = DateTime.UtcNow; - dbContext.Roles.Update(entity); - } - } - - /// - /// 保存仓储变更。 - /// - /// 取消标记。 - /// 保存任务。 - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - => dbContext.SaveChangesAsync(cancellationToken); -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfRoleTemplateRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfRoleTemplateRepository.cs deleted file mode 100644 index e84131d..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfRoleTemplateRepository.cs +++ /dev/null @@ -1,193 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Identity.Entities; -using TakeoutSaaS.Domain.Identity.Repositories; - -namespace TakeoutSaaS.Infrastructure.Identity.Persistence; - -/// -/// 角色模板仓储实现。 -/// -public sealed class EfRoleTemplateRepository(IdentityDbContext dbContext) : IRoleTemplateRepository -{ - /// - /// 获取全部角色模板,可选按启用状态过滤。 - /// - /// 是否启用过滤。 - /// 取消标记。 - /// 角色模板列表。 - public Task> GetAllAsync(bool? isActive, CancellationToken cancellationToken = default) - { - // 1. 构建基础查询 - var query = dbContext.RoleTemplates.AsNoTracking(); - if (isActive.HasValue) - { - // 2. 按启用状态过滤 - query = query.Where(x => x.IsActive == isActive.Value); - } - - // 3. 排序并返回 - return query - .OrderBy(x => x.TemplateCode) - .ToListAsync(cancellationToken) - .ContinueWith(t => (IReadOnlyList)t.Result, cancellationToken); - } - - /// - /// 根据模板编码获取角色模板。 - /// - /// 模板编码。 - /// 取消标记。 - /// 角色模板或 null。 - public Task FindByCodeAsync(string templateCode, CancellationToken cancellationToken = default) - { - // 1. 规范化编码 - var normalized = templateCode.Trim(); - // 2. 查询模板 - return dbContext.RoleTemplates.AsNoTracking().FirstOrDefaultAsync(x => x.TemplateCode == normalized, cancellationToken); - } - - /// - /// 获取指定模板的权限集合。 - /// - /// 模板 ID。 - /// 取消标记。 - /// 模板权限列表。 - public Task> GetPermissionsAsync(long roleTemplateId, CancellationToken cancellationToken = default) - { - // 1. 查询模板权限 - return dbContext.RoleTemplatePermissions.AsNoTracking() - .Where(x => x.RoleTemplateId == roleTemplateId) - .ToListAsync(cancellationToken) - .ContinueWith(t => (IReadOnlyList)t.Result, cancellationToken); - } - - /// - /// 获取多个模板的权限集合。 - /// - /// 模板 ID 集合。 - /// 取消标记。 - /// 模板到权限的字典。 - public async Task>> GetPermissionsAsync(IEnumerable roleTemplateIds, CancellationToken cancellationToken = default) - { - // 1. 去重 ID - var ids = roleTemplateIds.Distinct().ToArray(); - if (ids.Length == 0) - { - return new Dictionary>(); - } - - // 2. 批量查询权限 - var permissions = await dbContext.RoleTemplatePermissions.AsNoTracking() - .Where(x => ids.Contains(x.RoleTemplateId)) - .ToListAsync(cancellationToken); - - // 3. 组装字典 - return permissions - .GroupBy(x => x.RoleTemplateId) - .ToDictionary(g => g.Key, g => (IReadOnlyList)g.ToList()); - } - - /// - /// 新增角色模板并配置权限。 - /// - /// 角色模板实体。 - /// 权限编码集合。 - /// 取消标记。 - /// 异步任务。 - public async Task AddAsync(RoleTemplate template, IEnumerable permissionCodes, CancellationToken cancellationToken = default) - { - // 1. 规范化模板字段 - template.TemplateCode = template.TemplateCode.Trim(); - template.Name = template.Name.Trim(); - // 2. 保存模板 - await dbContext.RoleTemplates.AddAsync(template, cancellationToken); - // 3. 替换权限 - await ReplacePermissionsInternalAsync(template, permissionCodes, cancellationToken); - } - - /// - /// 更新角色模板并重置权限。 - /// - /// 角色模板实体。 - /// 权限编码集合。 - /// 取消标记。 - /// 异步任务。 - public async Task UpdateAsync(RoleTemplate template, IEnumerable permissionCodes, CancellationToken cancellationToken = default) - { - // 1. 规范化模板字段 - template.TemplateCode = template.TemplateCode.Trim(); - template.Name = template.Name.Trim(); - // 2. 更新模板 - dbContext.RoleTemplates.Update(template); - // 3. 重置权限 - await ReplacePermissionsInternalAsync(template, permissionCodes, cancellationToken); - } - - /// - /// 删除角色模板及其权限。 - /// - /// 模板 ID。 - /// 取消标记。 - /// 异步任务。 - public async Task DeleteAsync(long roleTemplateId, CancellationToken cancellationToken = default) - { - // 1. 查询模板 - var entity = await dbContext.RoleTemplates.FirstOrDefaultAsync(x => x.Id == roleTemplateId, cancellationToken); - if (entity != null) - { - // 2. 删除关联权限 - var permissions = dbContext.RoleTemplatePermissions.Where(x => x.RoleTemplateId == roleTemplateId); - dbContext.RoleTemplatePermissions.RemoveRange(permissions); - // 3. 删除模板 - dbContext.RoleTemplates.Remove(entity); - } - } - - /// - /// 保存仓储变更。 - /// - /// 取消标记。 - /// 保存任务。 - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - => dbContext.SaveChangesAsync(cancellationToken); - - private async Task ReplacePermissionsInternalAsync(RoleTemplate template, IEnumerable permissionCodes, CancellationToken cancellationToken) - { - // 1. 使用执行策略保证一致性 - var strategy = dbContext.Database.CreateExecutionStrategy(); - await strategy.ExecuteAsync(async () => - { - await using var trx = await dbContext.Database.BeginTransactionAsync(cancellationToken); - - // 1. 确保模板已持久化,便于 FK 正确填充 - if (!dbContext.Entry(template).IsKeySet || template.Id == 0) - { - await dbContext.SaveChangesAsync(cancellationToken); - } - - // 2. 归一化权限编码 - var normalized = permissionCodes - .Where(code => !string.IsNullOrWhiteSpace(code)) - .Select(code => code.Trim()) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToArray(); - - // 3. 清空旧权限(原生 SQL 避免跟踪干扰) - await dbContext.Database.ExecuteSqlRawAsync( - "DELETE FROM \"role_template_permissions\" WHERE \"RoleTemplateId\" = {0};", - parameters: new object[] { template.Id }, - cancellationToken: cancellationToken); - - // 4. 插入新权限(ON CONFLICT DO NOTHING 防御重复) - foreach (var code in normalized) - { - await dbContext.Database.ExecuteSqlRawAsync( - "INSERT INTO \"role_template_permissions\" (\"RoleTemplateId\",\"PermissionCode\",\"CreatedAt\",\"CreatedBy\",\"UpdatedAt\",\"UpdatedBy\",\"DeletedAt\",\"DeletedBy\") VALUES ({0},{1},NOW(),NULL,NULL,NULL,NULL,NULL) ON CONFLICT DO NOTHING;", - parameters: new object[] { template.Id, code }, - cancellationToken: cancellationToken); - } - - await trx.CommitAsync(cancellationToken); - }); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfUserRoleRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfUserRoleRepository.cs deleted file mode 100644 index c5398c2..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfUserRoleRepository.cs +++ /dev/null @@ -1,133 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Identity.Entities; -using TakeoutSaaS.Domain.Identity.Repositories; - -namespace TakeoutSaaS.Infrastructure.Identity.Persistence; - -/// -/// EF 用户-角色仓储。 -/// -public sealed class EfUserRoleRepository(IdentityDbContext dbContext) : IUserRoleRepository -{ - /// - /// 根据用户 ID 集合获取用户角色映射。 - /// - /// 租户 ID。 - /// 用户 ID 集合。 - /// 取消标记。 - /// 用户角色映射列表。 - public async Task> GetByUserIdsAsync(long tenantId, IEnumerable userIds, CancellationToken cancellationToken = default) - { - // 1. 查询用户角色映射 - var mappings = await dbContext.UserRoles - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.DeletedAt == null && userIds.Contains(x.UserId)) - .ToListAsync(cancellationToken); - - // 2. (空行后) 返回只读列表 - return mappings; - } - - /// - /// 获取指定用户的角色集合。 - /// - /// 租户 ID。 - /// 用户 ID。 - /// 取消标记。 - /// 用户角色列表。 - public async Task> GetByUserIdAsync(long tenantId, long userId, CancellationToken cancellationToken = default) - { - // 1. 查询用户角色映射 - var mappings = await dbContext.UserRoles - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.DeletedAt == null && x.UserId == userId) - .ToListAsync(cancellationToken); - - // 2. (空行后) 返回只读列表 - return mappings; - } - - /// - /// 替换指定用户的角色集合。 - /// - /// 租户 ID。 - /// 用户 ID。 - /// 角色 ID 集合。 - /// 取消标记。 - /// 异步任务。 - public async Task ReplaceUserRolesAsync(long tenantId, long userId, IEnumerable roleIds, CancellationToken cancellationToken = default) - { - // 1. 使用执行策略保障一致性 - var strategy = dbContext.Database.CreateExecutionStrategy(); - await strategy.ExecuteAsync(async () => - { - await using var trx = await dbContext.Database.BeginTransactionAsync(cancellationToken); - - // 2. 读取当前角色映射 - using var disableSoftDeleteScope = dbContext.DisableSoftDeleteFilter(); - var existing = await dbContext.UserRoles - .Where(x => x.TenantId == tenantId && x.UserId == userId) - .ToListAsync(cancellationToken); - - // 3. 去重并构建目标集合 - var targetRoleIds = roleIds.Distinct().ToArray(); - var targetRoleSet = targetRoleIds.ToHashSet(); - var existingRoleMap = existing.ToDictionary(x => x.RoleId); - - // 4. 同步现有映射状态(软删除或恢复) - foreach (var mapping in existing) - { - if (targetRoleSet.Contains(mapping.RoleId)) - { - if (mapping.DeletedAt.HasValue) - { - mapping.DeletedAt = null; - mapping.DeletedBy = null; - } - continue; - } - - if (!mapping.DeletedAt.HasValue) - { - dbContext.UserRoles.Remove(mapping); - } - } - - // 5. 补齐新增角色映射 - var toAdd = targetRoleIds - .Where(roleId => !existingRoleMap.ContainsKey(roleId)) - .Select(roleId => new UserRole - { - TenantId = tenantId, - UserId = userId, - RoleId = roleId - }); - - await dbContext.UserRoles.AddRangeAsync(toAdd, cancellationToken); - await dbContext.SaveChangesAsync(cancellationToken); - - await trx.CommitAsync(cancellationToken); - }); - } - - /// - /// 统计指定角色下的用户数量。 - /// - /// 租户 ID。 - /// 角色 ID。 - /// 取消标记。 - /// 用户数量。 - public Task CountUsersByRoleAsync(long tenantId, long roleId, CancellationToken cancellationToken = default) - => dbContext.UserRoles - .AsNoTracking() - .Where(x => x.TenantId == tenantId && x.DeletedAt == null && x.RoleId == roleId) - .CountAsync(cancellationToken); - - /// - /// 保存仓储变更。 - /// - /// 取消标记。 - /// 保存任务。 - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - => dbContext.SaveChangesAsync(cancellationToken); -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/IdentityDataSeeder.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/IdentityDataSeeder.cs deleted file mode 100644 index cf2c903..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/IdentityDataSeeder.cs +++ /dev/null @@ -1,326 +0,0 @@ -using Microsoft.AspNetCore.Identity; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Npgsql; -using TakeoutSaaS.Infrastructure.Identity.Options; -using TakeoutSaaS.Shared.Abstractions.Tenancy; -using DomainIdentityUser = TakeoutSaaS.Domain.Identity.Entities.IdentityUser; -using DomainPermission = TakeoutSaaS.Domain.Identity.Entities.Permission; -using DomainRole = TakeoutSaaS.Domain.Identity.Entities.Role; -using DomainRolePermission = TakeoutSaaS.Domain.Identity.Entities.RolePermission; -using DomainRoleTemplate = TakeoutSaaS.Domain.Identity.Entities.RoleTemplate; -using DomainRoleTemplatePermission = TakeoutSaaS.Domain.Identity.Entities.RoleTemplatePermission; -using DomainUserRole = TakeoutSaaS.Domain.Identity.Entities.UserRole; - -namespace TakeoutSaaS.Infrastructure.Identity.Persistence; - -/// -/// 后台账号初始化种子任务 -/// -public sealed class IdentityDataSeeder(IServiceProvider serviceProvider, ILogger logger) : IHostedService -{ - /// - /// 执行后台账号与权限种子。 - /// - /// 取消标记。 - /// 异步任务。 - public async Task StartAsync(CancellationToken cancellationToken) - { - // 1. 创建作用域并解析依赖 - using var scope = serviceProvider.CreateScope(); - var context = scope.ServiceProvider.GetRequiredService(); - var options = scope.ServiceProvider.GetRequiredService>().Value; - var passwordHasher = scope.ServiceProvider.GetRequiredService>(); - var tenantContextAccessor = scope.ServiceProvider.GetRequiredService(); - - // 2. 校验功能开关 - if (!options.Enabled) - { - logger.LogInformation("AdminSeed 已禁用,跳过后台账号初始化"); - return; - } - // 3. 确保数据库已迁移 - await context.Database.MigrateAsync(cancellationToken); - - // 4. 校验账号配置 - if (options.Users is null or { Count: 0 }) - { - logger.LogInformation("AdminSeed 未配置账号,跳过后台账号初始化"); - return; - } - - // 5. 写入角色模板 - await SeedRoleTemplatesAsync(context, options.RoleTemplates, cancellationToken); - - // 6. 逐个账号处理 - foreach (var userOptions in options.Users) - { - // 6.1 进入租户作用域 - using var tenantScope = tenantContextAccessor.EnterTenantScope(userOptions.TenantId, "admin-seed"); - // 6.2 查询账号并收集配置 - var user = await context.IdentityUsers.FirstOrDefaultAsync(x => x.Account == userOptions.Account, cancellationToken); - var roles = NormalizeValues(userOptions.Roles); - var permissions = NormalizeValues(userOptions.Permissions); - - if (user == null) - { - // 6.3 创建新账号 - user = new DomainIdentityUser - { - Id = 0, - Account = userOptions.Account, - DisplayName = userOptions.DisplayName, - TenantId = userOptions.TenantId, - MerchantId = userOptions.MerchantId, - Avatar = null - }; - user.PasswordHash = passwordHasher.HashPassword(user, userOptions.Password); - context.IdentityUsers.Add(user); - logger.LogInformation("已创建后台账号 {Account}", user.Account); - } - else - { - // 6.4 更新既有账号 - user.DisplayName = userOptions.DisplayName; - user.TenantId = userOptions.TenantId; - user.MerchantId = userOptions.MerchantId; - user.PasswordHash = passwordHasher.HashPassword(user, userOptions.Password); - logger.LogInformation("已更新后台账号 {Account}", user.Account); - } - - // 6.5 确保角色存在 - var existingRoles = await context.Roles - .Where(r => r.TenantId == userOptions.TenantId && roles.Contains(r.Code)) - .ToListAsync(cancellationToken); - var existingRoleCodes = existingRoles.Select(r => r.Code).ToHashSet(StringComparer.OrdinalIgnoreCase); - foreach (var code in roles) - { - if (existingRoleCodes.Contains(code)) - { - continue; - } - - context.Roles.Add(new DomainRole - { - TenantId = userOptions.TenantId, - Code = code, - Name = code, - Description = $"Seed role {code}" - }); - } - - // 6.6 读取当前租户权限定义 - var existingPermissions = await context.Permissions - .AsNoTracking() - .Where(p => permissions.Contains(p.Code)) - .ToListAsync(cancellationToken); - var existingPermissionCodes = existingPermissions - .Select(p => p.Code) - .ToHashSet(StringComparer.OrdinalIgnoreCase); - var missingPermissionCodes = permissions - .Where(code => !existingPermissionCodes.Contains(code)) - .ToArray(); - if (missingPermissionCodes.Length > 0) - { - logger.LogWarning("发现未配置的全局权限编码,已忽略:{Codes}", string.Join(", ", missingPermissionCodes)); - } - - // 6.7 保存基础角色/权限 - await context.SaveChangesAsync(cancellationToken); - - // 6.8 重新加载角色/权限以获取 Id - var roleEntities = await context.Roles - .Where(r => r.TenantId == userOptions.TenantId && roles.Contains(r.Code)) - .ToListAsync(cancellationToken); - var permissionEntities = existingPermissions; - - // 6.9 重置用户角色 - var existingUserRoles = await context.UserRoles - .Where(ur => ur.TenantId == userOptions.TenantId && ur.UserId == user.Id) - .ToListAsync(cancellationToken); - context.UserRoles.RemoveRange(existingUserRoles); - await context.SaveChangesAsync(cancellationToken); - - var roleIds = roleEntities.Select(r => r.Id).Distinct().ToArray(); - foreach (var roleId in roleIds) - { - try - { - var alreadyExists = await context.UserRoles.AnyAsync( - ur => ur.TenantId == userOptions.TenantId && ur.UserId == user.Id && ur.RoleId == roleId, - cancellationToken); - if (alreadyExists) - { - continue; - } - - await context.UserRoles.AddAsync(new DomainUserRole - { - TenantId = userOptions.TenantId, - UserId = user.Id, - RoleId = roleId - }, cancellationToken); - - await context.SaveChangesAsync(cancellationToken); - } - catch (DbUpdateException ex) when (ex.InnerException is PostgresException pg && pg.SqlState == PostgresErrorCodes.UniqueViolation) - { - context.ChangeTracker.Clear(); - } - } - - // 为种子角色绑定种子权限 - if (permissions.Length > 0 && roleIds.Length > 0) - { - var permissionIds = permissionEntities.Select(p => p.Id).Distinct().ToArray(); - var existingRolePermissions = await context.RolePermissions - .Where(rp => rp.TenantId == userOptions.TenantId && roleIds.Contains(rp.RoleId)) - .ToListAsync(cancellationToken); - context.RolePermissions.RemoveRange(existingRolePermissions); - await context.SaveChangesAsync(cancellationToken); - - var distinctRoleIds = roleIds.Distinct().ToArray(); - var distinctPermissionIds = permissionIds.Distinct().ToArray(); - foreach (var roleId in distinctRoleIds) - { - foreach (var permissionId in distinctPermissionIds) - { - try - { - var exists = await context.RolePermissions.AnyAsync( - rp => rp.TenantId == userOptions.TenantId - && rp.RoleId == roleId - && rp.PermissionId == permissionId, - cancellationToken); - if (exists) - { - continue; - } - - // 6.10 绑定角色与权限 - await context.RolePermissions.AddAsync(new DomainRolePermission - { - TenantId = userOptions.TenantId, - RoleId = roleId, - PermissionId = permissionId - }, cancellationToken); - - await context.SaveChangesAsync(cancellationToken); - } - catch (DbUpdateException ex) when (ex.InnerException is PostgresException pg && pg.SqlState == PostgresErrorCodes.UniqueViolation) - { - context.ChangeTracker.Clear(); - } - } - } - } - } - - // 7. 最终保存 - await context.SaveChangesAsync(cancellationToken); - } - - /// - /// 停止生命周期时的清理(此处无需处理)。 - /// - /// 取消标记。 - /// 已完成任务。 - public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; - - private static async Task SeedRoleTemplatesAsync( - IdentityDbContext context, - IList templates, - CancellationToken cancellationToken) - { - // 1. 空集合直接返回 - if (templates is null || templates.Count == 0) - { - return; - } - - // 2. 逐个处理模板 - foreach (var templateOptions in templates) - { - // 2.1 校验必填字段 - if (string.IsNullOrWhiteSpace(templateOptions.TemplateCode) || string.IsNullOrWhiteSpace(templateOptions.Name)) - { - continue; - } - - // 2.2 查询现有模板 - var code = templateOptions.TemplateCode.Trim(); - var existing = await context.RoleTemplates.FirstOrDefaultAsync(x => x.TemplateCode == code, cancellationToken); - - if (existing == null) - { - // 2.3 新增模板 - existing = new DomainRoleTemplate - { - TemplateCode = code, - Name = templateOptions.Name.Trim(), - Description = templateOptions.Description, - IsActive = templateOptions.IsActive - }; - - await context.RoleTemplates.AddAsync(existing, cancellationToken); - await context.SaveChangesAsync(cancellationToken); - } - else - { - // 2.4 更新模板 - existing.Name = templateOptions.Name.Trim(); - existing.Description = templateOptions.Description; - existing.IsActive = templateOptions.IsActive; - context.RoleTemplates.Update(existing); - await context.SaveChangesAsync(cancellationToken); - } - - // 2.5 重置模板权限 - var permissionCodes = NormalizeValues(templateOptions.Permissions); - var existingPermissions = await context.RoleTemplatePermissions - .Where(x => x.RoleTemplateId == existing.Id) - .ToListAsync(cancellationToken); - // 2.6 清空旧权限并保存 - context.RoleTemplatePermissions.RemoveRange(existingPermissions); - await context.SaveChangesAsync(cancellationToken); - // 2.7 去重后的权限编码 - var distinctPermissionCodes = permissionCodes.Distinct(StringComparer.OrdinalIgnoreCase).ToArray(); - foreach (var permissionCode in distinctPermissionCodes) - { - try - { - var alreadyExists = await context.RoleTemplatePermissions.AnyAsync( - x => x.RoleTemplateId == existing.Id && x.PermissionCode == permissionCode, - cancellationToken); - if (alreadyExists) - { - continue; - } - - await context.RoleTemplatePermissions.AddAsync(new DomainRoleTemplatePermission - { - RoleTemplateId = existing.Id, - PermissionCode = permissionCode - }, cancellationToken); - - await context.SaveChangesAsync(cancellationToken); - } - catch (DbUpdateException ex) when (ex.InnerException is PostgresException pg && pg.SqlState == PostgresErrorCodes.UniqueViolation) - { - context.ChangeTracker.Clear(); - } - } - } - } - - private static string[] NormalizeValues(string[]? values) - => values == null - ? [] - : [.. values - .Where(v => !string.IsNullOrWhiteSpace(v)) - .Select(v => v.Trim()) - .Distinct(StringComparer.OrdinalIgnoreCase)]; -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/IdentityDbContext.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/IdentityDbContext.cs deleted file mode 100644 index 818fe13..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/IdentityDbContext.cs +++ /dev/null @@ -1,246 +0,0 @@ -using MassTransit; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; -using TakeoutSaaS.Domain.Identity.Entities; -using TakeoutSaaS.Infrastructure.Common.Persistence; -using TakeoutSaaS.Shared.Abstractions.Ids; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Infrastructure.Identity.Persistence; - -/// -/// 身份认证 DbContext,带多租户过滤与审计字段处理。 -/// -public sealed class IdentityDbContext( - DbContextOptions options, - ITenantProvider tenantProvider, - ICurrentUserAccessor? currentUserAccessor = null, - IIdGenerator? idGenerator = null) - : TenantAwareDbContext(options, tenantProvider, currentUserAccessor, idGenerator) -{ - /// - /// 管理后台用户集合。 - /// - public DbSet IdentityUsers => Set(); - - /// - /// 小程序用户集合。 - /// - public DbSet MiniUsers => Set(); - - /// - /// 角色集合。 - /// - public DbSet Roles => Set(); - - /// - /// 角色模板集合(系统级)。 - /// - public DbSet RoleTemplates => Set(); - - /// - /// 角色模板权限集合。 - /// - public DbSet RoleTemplatePermissions => Set(); - - /// - /// 权限集合。 - /// - public DbSet Permissions => Set(); - - /// - /// 用户-角色关系。 - /// - public DbSet UserRoles => Set(); - - /// - /// 角色-权限关系。 - /// - public DbSet RolePermissions => Set(); - - /// - /// 菜单定义集合。 - /// - public DbSet MenuDefinitions => Set(); - - /// - /// 配置实体模型。 - /// - /// 模型构建器。 - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - base.OnModelCreating(modelBuilder); - ConfigureIdentityUser(modelBuilder.Entity()); - ConfigureMiniUser(modelBuilder.Entity()); - ConfigureRole(modelBuilder.Entity()); - ConfigureRoleTemplate(modelBuilder.Entity()); - ConfigureRoleTemplatePermission(modelBuilder.Entity()); - ConfigurePermission(modelBuilder.Entity()); - ConfigureUserRole(modelBuilder.Entity()); - ConfigureRolePermission(modelBuilder.Entity()); - ConfigureMenuDefinition(modelBuilder.Entity()); - modelBuilder.AddOutboxMessageEntity(); - modelBuilder.AddOutboxStateEntity(); - ApplyTenantQueryFilters(modelBuilder); - } - - /// - /// 配置管理后台用户实体。 - /// - /// 实体构建器。 - private static void ConfigureIdentityUser(EntityTypeBuilder builder) - { - builder.ToTable("identity_users"); - builder.HasKey(x => x.Id); - builder.Property(x => x.Account).HasMaxLength(64).IsRequired(); - builder.Property(x => x.DisplayName).HasMaxLength(64).IsRequired(); - builder.Property(x => x.PasswordHash).HasMaxLength(256).IsRequired(); - builder.Property(x => x.Phone).HasMaxLength(32); - builder.Property(x => x.Email).HasMaxLength(128); - builder.Property(x => x.Status).HasConversion(); - builder.Property(x => x.FailedLoginCount).IsRequired(); - builder.Property(x => x.LockedUntil); - builder.Property(x => x.LastLoginAt); - builder.Property(x => x.MustChangePassword).IsRequired(); - builder.Property(x => x.Avatar).HasColumnType("text"); - builder.Ignore(x => x.RowVersion); - builder.Property("xmin") - .HasColumnName("xmin") - .HasColumnType("xid") - .ValueGeneratedOnAddOrUpdate() - .IsConcurrencyToken(); - builder.Property(x => x.TenantId).IsRequired(); - ConfigureAuditableEntity(builder); - ConfigureSoftDeleteEntity(builder); - - builder.HasIndex(x => x.TenantId); - builder.HasIndex(x => new { x.TenantId, x.Account }).IsUnique(); - builder.HasIndex(x => new { x.TenantId, x.Phone }) - .IsUnique() - .HasFilter("\"Phone\" IS NOT NULL"); - builder.HasIndex(x => new { x.TenantId, x.Email }) - .IsUnique() - .HasFilter("\"Email\" IS NOT NULL"); - } - - /// - /// 配置小程序用户实体。 - /// - /// 实体构建器。 - private static void ConfigureMiniUser(EntityTypeBuilder builder) - { - builder.ToTable("mini_users"); - builder.HasKey(x => x.Id); - builder.Property(x => x.TenantId).IsRequired(); - builder.Property(x => x.OpenId).HasMaxLength(128).IsRequired(); - builder.Property(x => x.UnionId).HasMaxLength(128); - builder.Property(x => x.Nickname).HasMaxLength(64).IsRequired(); - builder.Property(x => x.Avatar).HasColumnType("text"); - ConfigureAuditableEntity(builder); - ConfigureSoftDeleteEntity(builder); - - builder.HasIndex(x => x.TenantId); - builder.HasIndex(x => new { x.TenantId, x.OpenId }).IsUnique(); - } - - private static void ConfigureRole(EntityTypeBuilder builder) - { - builder.ToTable("roles"); - builder.HasKey(x => x.Id); - builder.Property(x => x.TenantId).IsRequired(); - builder.Property(x => x.Name).HasMaxLength(64).IsRequired(); - builder.Property(x => x.Code).HasMaxLength(64).IsRequired(); - builder.Property(x => x.Description).HasMaxLength(256); - ConfigureAuditableEntity(builder); - ConfigureSoftDeleteEntity(builder); - builder.HasIndex(x => x.TenantId); - builder.HasIndex(x => new { x.TenantId, x.Code }).IsUnique(); - } - - private static void ConfigurePermission(EntityTypeBuilder builder) - { - builder.ToTable("permissions"); - builder.HasKey(x => x.Id); - builder.Property(x => x.ParentId).IsRequired(); - builder.Property(x => x.SortOrder).IsRequired(); - builder.Property(x => x.Type).HasMaxLength(16).IsRequired(); - builder.Property(x => x.Name).HasMaxLength(64).IsRequired(); - builder.Property(x => x.Code).HasMaxLength(128).IsRequired(); - builder.Property(x => x.Description).HasMaxLength(256); - ConfigureAuditableEntity(builder); - ConfigureSoftDeleteEntity(builder); - builder.HasIndex(x => x.Code).IsUnique(); - builder.HasIndex(x => new { x.Portal, x.ParentId, x.SortOrder }); - } - - private static void ConfigureRoleTemplate(EntityTypeBuilder builder) - { - builder.ToTable("role_templates"); - builder.HasKey(x => x.Id); - builder.Property(x => x.TemplateCode).HasMaxLength(64).IsRequired(); - builder.Property(x => x.Name).HasMaxLength(128).IsRequired(); - builder.Property(x => x.Description).HasMaxLength(256); - builder.Property(x => x.IsActive).IsRequired(); - ConfigureAuditableEntity(builder); - builder.HasIndex(x => x.TemplateCode).IsUnique(); - } - - private static void ConfigureRoleTemplatePermission(EntityTypeBuilder builder) - { - builder.ToTable("role_template_permissions"); - builder.HasKey(x => x.Id); - builder.Property(x => x.RoleTemplateId).IsRequired(); - builder.Property(x => x.PermissionCode).HasMaxLength(128).IsRequired(); - ConfigureAuditableEntity(builder); - builder.HasIndex(x => new { x.RoleTemplateId, x.PermissionCode }).IsUnique(); - } - - private static void ConfigureUserRole(EntityTypeBuilder builder) - { - builder.ToTable("user_roles"); - builder.HasKey(x => x.Id); - builder.Property(x => x.TenantId).IsRequired(); - builder.Property(x => x.UserId).IsRequired(); - builder.Property(x => x.RoleId).IsRequired(); - ConfigureAuditableEntity(builder); - ConfigureSoftDeleteEntity(builder); - builder.HasIndex(x => x.TenantId); - builder.HasIndex(x => new { x.TenantId, x.UserId, x.RoleId }).IsUnique(); - } - - private static void ConfigureRolePermission(EntityTypeBuilder builder) - { - builder.ToTable("role_permissions"); - builder.HasKey(x => x.Id); - builder.Property(x => x.TenantId).IsRequired(); - builder.Property(x => x.RoleId).IsRequired(); - builder.Property(x => x.PermissionId).IsRequired(); - ConfigureAuditableEntity(builder); - ConfigureSoftDeleteEntity(builder); - builder.HasIndex(x => x.TenantId); - builder.HasIndex(x => new { x.TenantId, x.RoleId, x.PermissionId }).IsUnique(); - } - - private static void ConfigureMenuDefinition(EntityTypeBuilder builder) - { - builder.ToTable("menu_definitions"); - builder.HasKey(x => x.Id); - builder.Property(x => x.Portal).HasConversion().IsRequired(); - builder.Property(x => x.ParentId).IsRequired(); - builder.Property(x => x.Name).HasMaxLength(64).IsRequired(); - builder.Property(x => x.Path).HasMaxLength(256).IsRequired(); - builder.Property(x => x.Component).HasMaxLength(256).IsRequired(); - builder.Property(x => x.Title).HasMaxLength(128).IsRequired(); - builder.Property(x => x.Icon).HasMaxLength(64); - builder.Property(x => x.Link).HasMaxLength(512); - builder.Property(x => x.SortOrder).IsRequired(); - builder.Property(x => x.RequiredPermissions).HasMaxLength(1024); - builder.Property(x => x.MetaPermissions).HasMaxLength(1024); - builder.Property(x => x.MetaRoles).HasMaxLength(1024); - builder.Property(x => x.AuthListJson).HasColumnType("text"); - ConfigureAuditableEntity(builder); - ConfigureSoftDeleteEntity(builder); - builder.HasIndex(x => new { x.Portal, x.ParentId, x.SortOrder }); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/IdentityDesignTimeDbContextFactory.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/IdentityDesignTimeDbContextFactory.cs deleted file mode 100644 index 926cba6..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/IdentityDesignTimeDbContextFactory.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Infrastructure.Common.Persistence.DesignTime; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Infrastructure.Identity.Persistence; - -/// -/// 设计时 IdentityDbContext 工厂,供 EF Core CLI 生成迁移使用。 -/// -internal sealed class IdentityDesignTimeDbContextFactory - : DesignTimeDbContextFactoryBase -{ - /// - /// 初始化 Identity 设计时上下文工厂。 - /// - public IdentityDesignTimeDbContextFactory() - : base(DatabaseConstants.IdentityDataSource, "TAKEOUTSAAS_IDENTITY_CONNECTION") - { - } - // 创建设计时上下文实例 - /// - /// 创建设计时的 IdentityDbContext。 - /// - /// DbContext 配置。 - /// 租户提供器。 - /// 当前用户访问器。 - /// IdentityDbContext 实例。 - protected override IdentityDbContext CreateContext( - DbContextOptions options, - ITenantProvider tenantProvider, - ICurrentUserAccessor currentUserAccessor) - => new(options, tenantProvider, currentUserAccessor); -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Repositories/EfMenuRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Repositories/EfMenuRepository.cs deleted file mode 100644 index 5173e3c..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Repositories/EfMenuRepository.cs +++ /dev/null @@ -1,72 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Identity.Entities; -using TakeoutSaaS.Domain.Identity.Enums; -using TakeoutSaaS.Domain.Identity.Repositories; -using TakeoutSaaS.Infrastructure.Identity.Persistence; - -namespace TakeoutSaaS.Infrastructure.Identity.Repositories; - -/// -/// 菜单仓储 EF 实现。 -/// -public sealed class EfMenuRepository(IdentityDbContext dbContext) : IMenuRepository -{ - /// - public async Task> GetByPortalAsync(PortalType portal, CancellationToken cancellationToken = default) - { - // 1. 按门户类型查询菜单(忽略租户过滤器) - var menus = await dbContext.MenuDefinitions - .IgnoreQueryFilters() - .AsNoTracking() - .Where(x => x.Portal == portal && x.DeletedAt == null) - .OrderBy(x => x.ParentId) - .ThenBy(x => x.SortOrder) - .ToListAsync(cancellationToken); - - return menus; - } - - /// - public async Task FindByIdAsync(long id, CancellationToken cancellationToken = default) - { - // 1. 按 ID 查询菜单(忽略租户过滤器) - return await dbContext.MenuDefinitions - .IgnoreQueryFilters() - .AsNoTracking() - .FirstOrDefaultAsync(x => x.Id == id && x.DeletedAt == null, cancellationToken); - } - - /// - public Task AddAsync(MenuDefinition menu, CancellationToken cancellationToken = default) - { - return dbContext.MenuDefinitions.AddAsync(menu, cancellationToken).AsTask(); - } - - /// - public Task UpdateAsync(MenuDefinition menu, CancellationToken cancellationToken = default) - { - dbContext.MenuDefinitions.Update(menu); - return Task.CompletedTask; - } - - /// - public async Task DeleteAsync(long id, CancellationToken cancellationToken = default) - { - // 1. 查询目标(忽略租户过滤器) - var entity = await dbContext.MenuDefinitions - .IgnoreQueryFilters() - .FirstOrDefaultAsync(x => x.Id == id, cancellationToken); - - // 2. 存在则删除 - if (entity is not null) - { - dbContext.MenuDefinitions.Remove(entity); - } - } - - /// - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - { - return dbContext.SaveChangesAsync(cancellationToken); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Services/JwtTokenService.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Services/JwtTokenService.cs deleted file mode 100644 index 71c3080..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Services/JwtTokenService.cs +++ /dev/null @@ -1,95 +0,0 @@ -using Microsoft.Extensions.Options; -using Microsoft.IdentityModel.Tokens; -using System.IdentityModel.Tokens.Jwt; -using System.Security.Claims; -using System.Text; -using TakeoutSaaS.Application.Identity.Abstractions; -using TakeoutSaaS.Application.Identity.Contracts; -using TakeoutSaaS.Infrastructure.Identity.Options; - -namespace TakeoutSaaS.Infrastructure.Identity.Services; - -/// -/// JWT 令牌生成器。 -/// -public sealed class JwtTokenService(IRefreshTokenStore refreshTokenStore, IOptions options) : IJwtTokenService -{ - private readonly JwtSecurityTokenHandler _tokenHandler = new(); - private readonly JwtOptions _options = options.Value; - - /// - /// 创建访问令牌和刷新令牌对。 - /// - /// 用户档案 - /// 是否为新用户(首次登录) - /// 取消令牌 - /// 令牌响应 - public async Task CreateTokensAsync(CurrentUserProfile profile, bool isNewUser = false, CancellationToken cancellationToken = default) - { - var now = DateTime.UtcNow; - var accessExpires = now.AddMinutes(_options.AccessTokenExpirationMinutes); - var refreshExpires = now.AddMinutes(_options.RefreshTokenExpirationMinutes); - - // 1. 构建 JWT Claims(包含用户 ID、账号、租户 ID、商户 ID、角色、权限等) - var claims = BuildClaims(profile); - - // 2. 创建签名凭据(使用 HMAC SHA256 算法) - var signingCredentials = new SigningCredentials( - new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_options.Secret)), - SecurityAlgorithms.HmacSha256); - - // 3. 创建 JWT 安全令牌 - var jwt = new JwtSecurityToken( - issuer: _options.Issuer, - audience: _options.Audience, - claims: claims, - notBefore: now, - expires: accessExpires, - signingCredentials: signingCredentials); - - // 4. 序列化 JWT 为字符串 - var accessToken = _tokenHandler.WriteToken(jwt); - - // 5. 生成刷新令牌并存储到 Redis - var refreshDescriptor = await refreshTokenStore.IssueAsync(profile.UserId, refreshExpires, cancellationToken); - - return new TokenResponse - { - AccessToken = accessToken, - AccessTokenExpiresAt = accessExpires, - RefreshToken = refreshDescriptor.Token, - RefreshTokenExpiresAt = refreshDescriptor.ExpiresAt, - User = profile, - IsNewUser = isNewUser - }; - } - - /// - /// 构建 JWT Claims:将用户档案转换为 Claims 集合。 - /// - /// 用户档案 - /// Claims 集合 - private static List BuildClaims(CurrentUserProfile profile) - { - var userId = profile.UserId.ToString(); - var claims = new List - { - new(JwtRegisteredClaimNames.Sub, userId), - new(ClaimTypes.NameIdentifier, userId), - new(JwtRegisteredClaimNames.UniqueName, profile.Account), - new("tenant_id", profile.TenantId.ToString()), - new(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) - }; - - if (profile.MerchantId.HasValue) - { - claims.Add(new Claim("merchant_id", profile.MerchantId.Value.ToString())); - } - - claims.AddRange(profile.Roles.Select(role => new Claim(ClaimTypes.Role, role))); - - claims.AddRange(profile.Permissions.Select(permission => new Claim("permission", permission))); - - return claims; - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Services/RedisAdminPasswordResetTokenStore.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Services/RedisAdminPasswordResetTokenStore.cs deleted file mode 100644 index fad8217..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Services/RedisAdminPasswordResetTokenStore.cs +++ /dev/null @@ -1,66 +0,0 @@ -using Microsoft.Extensions.Caching.Distributed; -using Microsoft.Extensions.Options; -using System.Security.Cryptography; -using TakeoutSaaS.Application.Identity.Abstractions; -using TakeoutSaaS.Infrastructure.Identity.Options; - -namespace TakeoutSaaS.Infrastructure.Identity.Services; - -/// -/// Redis 管理后台重置密码链接令牌存储。 -/// -public sealed class RedisAdminPasswordResetTokenStore( - IDistributedCache cache, - IOptions options) - : IAdminPasswordResetTokenStore -{ - private readonly AdminPasswordResetOptions _options = options.Value; - - /// - public async Task IssueAsync(long userId, DateTime expiresAt, CancellationToken cancellationToken = default) - { - // 1. 生成 URL 安全的随机令牌 - var token = GenerateUrlSafeToken(48); - - // 2. 写入缓存(Value:userId) - await cache.SetStringAsync(BuildKey(token), userId.ToString(), new DistributedCacheEntryOptions - { - AbsoluteExpiration = expiresAt - }, cancellationToken); - - // 3. 返回令牌 - return token; - } - - /// - public async Task ConsumeAsync(string token, CancellationToken cancellationToken = default) - { - // 1. 读取缓存 - var key = BuildKey(token); - var value = await cache.GetStringAsync(key, cancellationToken); - if (string.IsNullOrWhiteSpace(value)) - { - return null; - } - - // 2. 删除缓存(一次性令牌) - await cache.RemoveAsync(key, cancellationToken); - - // 3. 解析用户 ID - return long.TryParse(value, out var userId) ? userId : null; - } - - private string BuildKey(string token) => $"{_options.Prefix}{token}"; - - private static string GenerateUrlSafeToken(int bytesLength) - { - var bytes = RandomNumberGenerator.GetBytes(bytesLength); - var token = Convert.ToBase64String(bytes); - - return token - .Replace('+', '-') - .Replace('/', '_') - .TrimEnd('='); - } -} - diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Services/RedisLoginRateLimiter.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Services/RedisLoginRateLimiter.cs deleted file mode 100644 index 94491e0..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Services/RedisLoginRateLimiter.cs +++ /dev/null @@ -1,56 +0,0 @@ -using Microsoft.Extensions.Caching.Distributed; -using Microsoft.Extensions.Options; -using TakeoutSaaS.Application.Identity.Abstractions; -using TakeoutSaaS.Infrastructure.Identity.Options; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; - -namespace TakeoutSaaS.Infrastructure.Identity.Services; - -/// -/// Redis 登录限流实现。 -/// -public sealed class RedisLoginRateLimiter(IDistributedCache cache, IOptions options) : ILoginRateLimiter -{ - private readonly LoginRateLimitOptions _options = options.Value; - - /// - /// 校验指定键的登录尝试次数,超限将抛出业务异常。 - /// - /// 限流键(如账号或 IP)。 - /// 取消标记。 - /// 异步任务。 - public async Task EnsureAllowedAsync(string key, CancellationToken cancellationToken = default) - { - // 1. 读取当前计数 - var cacheKey = BuildKey(key); - var current = await cache.GetStringAsync(cacheKey, cancellationToken); - var count = string.IsNullOrWhiteSpace(current) ? 0 : int.Parse(current); - if (count >= _options.MaxAttempts) - { - throw new BusinessException(ErrorCodes.Forbidden, "尝试次数过多,请稍后再试"); - } - - // 2. 累加计数并回写缓存 - count++; - await cache.SetStringAsync( - cacheKey, - count.ToString(), - new DistributedCacheEntryOptions - { - AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(_options.WindowSeconds) - }, - cancellationToken); - } - - /// - /// 重置指定键的登录计数。 - /// - /// 限流键(如账号或 IP)。 - /// 取消标记。 - /// 异步任务。 - public Task ResetAsync(string key, CancellationToken cancellationToken = default) - => cache.RemoveAsync(BuildKey(key), cancellationToken); - - private static string BuildKey(string key) => $"identity:login:{key}"; -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Services/RedisRefreshTokenStore.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Services/RedisRefreshTokenStore.cs deleted file mode 100644 index a1970c6..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Services/RedisRefreshTokenStore.cs +++ /dev/null @@ -1,77 +0,0 @@ -using Microsoft.Extensions.Caching.Distributed; -using Microsoft.Extensions.Options; -using System.Security.Cryptography; -using System.Text.Json; -using TakeoutSaaS.Application.Identity.Abstractions; -using TakeoutSaaS.Application.Identity.Models; -using TakeoutSaaS.Infrastructure.Identity.Options; - -namespace TakeoutSaaS.Infrastructure.Identity.Services; - -/// -/// Redis 刷新令牌存储。 -/// -public sealed class RedisRefreshTokenStore(IDistributedCache cache, IOptions options) : IRefreshTokenStore -{ - private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web); - private readonly RefreshTokenStoreOptions _options = options.Value; - - /// - /// 签发刷新令牌并写入缓存。 - /// - /// 用户 ID。 - /// 过期时间。 - /// 取消标记。 - /// 刷新令牌描述。 - public async Task IssueAsync(long userId, DateTime expiresAt, CancellationToken cancellationToken = default) - { - // 1. 生成随机令牌 - var token = Convert.ToBase64String(RandomNumberGenerator.GetBytes(48)); - var descriptor = new RefreshTokenDescriptor(token, userId, expiresAt, false); - - // 2. 写入缓存 - var key = BuildKey(token); - var entryOptions = new DistributedCacheEntryOptions { AbsoluteExpiration = expiresAt }; - await cache.SetStringAsync(key, JsonSerializer.Serialize(descriptor, JsonOptions), entryOptions, cancellationToken); - - return descriptor; - } - - /// - /// 获取刷新令牌描述。 - /// - /// 刷新令牌值。 - /// 取消标记。 - /// 刷新令牌描述或 null。 - public async Task GetAsync(string refreshToken, CancellationToken cancellationToken = default) - { - // 1. 读取缓存 - var json = await cache.GetStringAsync(BuildKey(refreshToken), cancellationToken); - return string.IsNullOrWhiteSpace(json) - ? null - : JsonSerializer.Deserialize(json, JsonOptions); - } - - /// - /// 吊销刷新令牌。 - /// - /// 刷新令牌值。 - /// 取消标记。 - /// 异步任务。 - public async Task RevokeAsync(string refreshToken, CancellationToken cancellationToken = default) - { - // 1. 读取令牌 - var descriptor = await GetAsync(refreshToken, cancellationToken); - if (descriptor == null) - { - return; - } - - // 2. 标记吊销并回写缓存 - var updated = descriptor with { Revoked = true }; - var entryOptions = new DistributedCacheEntryOptions { AbsoluteExpiration = updated.ExpiresAt }; - await cache.SetStringAsync(BuildKey(refreshToken), JsonSerializer.Serialize(updated, JsonOptions), entryOptions, cancellationToken); - } - - private string BuildKey(string token) => $"{_options.Prefix}{token}"; -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Services/WeChatAuthService.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Services/WeChatAuthService.cs deleted file mode 100644 index 272ffc9..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Services/WeChatAuthService.cs +++ /dev/null @@ -1,79 +0,0 @@ -using Microsoft.Extensions.Options; -using System.Net.Http.Json; -using System.Text.Json.Serialization; -using TakeoutSaaS.Application.Identity.Abstractions; -using TakeoutSaaS.Infrastructure.Identity.Options; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Exceptions; - -namespace TakeoutSaaS.Infrastructure.Identity.Services; - -/// -/// 微信 code2Session 实现 -/// -public sealed class WeChatAuthService(HttpClient httpClient, IOptions options) : IWeChatAuthService -{ - private readonly WeChatMiniOptions _options = options.Value; - - /// - /// 调用微信接口完成 code2Session。 - /// - /// 临时登录凭证 code。 - /// 取消标记。 - /// 微信会话信息。 - public async Task Code2SessionAsync(string code, CancellationToken cancellationToken = default) - { - // 1. 拼装请求地址 - var requestUri = $"sns/jscode2session?appid={Uri.EscapeDataString(_options.AppId)}&secret={Uri.EscapeDataString(_options.Secret)}&js_code={Uri.EscapeDataString(code)}&grant_type=authorization_code"; - using var response = await httpClient.GetAsync(requestUri, cancellationToken); - response.EnsureSuccessStatusCode(); - - // 2. 读取响应 - var payload = await response.Content.ReadFromJsonAsync(cancellationToken: cancellationToken); - if (payload == null) - { - throw new BusinessException(ErrorCodes.Unauthorized, "微信登录失败:响应为空"); - } - - // 3. 校验错误码 - if (payload.ErrorCode.HasValue && payload.ErrorCode.Value != 0) - { - var message = string.IsNullOrWhiteSpace(payload.ErrorMessage) - ? $"微信登录失败,错误码:{payload.ErrorCode}" - : payload.ErrorMessage; - throw new BusinessException(ErrorCodes.Unauthorized, message); - } - - // 4. 校验必要字段 - if (string.IsNullOrWhiteSpace(payload.OpenId) || string.IsNullOrWhiteSpace(payload.SessionKey)) - { - throw new BusinessException(ErrorCodes.Unauthorized, "微信登录失败:返回数据无效"); - } - - // 5. 组装会话信息 - return new WeChatSessionInfo - { - OpenId = payload.OpenId, - UnionId = payload.UnionId, - SessionKey = payload.SessionKey - }; - } - - private sealed class WeChatSessionResponse - { - [JsonPropertyName("openid")] - public string? OpenId { get; set; } - - [JsonPropertyName("unionid")] - public string? UnionId { get; set; } - - [JsonPropertyName("session_key")] - public string? SessionKey { get; set; } - - [JsonPropertyName("errcode")] - public int? ErrorCode { get; set; } - - [JsonPropertyName("errmsg")] - public string? ErrorMessage { get; set; } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Consumers/IdentityUserOperationLogConsumer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Consumers/IdentityUserOperationLogConsumer.cs deleted file mode 100644 index 0d92d0b..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Consumers/IdentityUserOperationLogConsumer.cs +++ /dev/null @@ -1,72 +0,0 @@ -using MassTransit; -using Microsoft.EntityFrameworkCore; -using Npgsql; -using TakeoutSaaS.Application.Identity.Events; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Infrastructure.Logs.Persistence; - -namespace TakeoutSaaS.Infrastructure.Logs.Consumers; - -/// -/// 身份用户操作日志消费者。 -/// -public sealed class IdentityUserOperationLogConsumer(TakeoutLogsDbContext logsContext) : IConsumer -{ - /// - public async Task Consume(ConsumeContext context) - { - // 1. 校验消息标识并进行幂等检查 - var messageId = context.MessageId; - if (!messageId.HasValue) - { - throw new InvalidOperationException("缺少 MessageId,无法进行日志幂等处理。"); - } - - var exists = await logsContext.OperationLogInboxMessages - .AsNoTracking() - .AnyAsync(x => x.MessageId == messageId.Value, context.CancellationToken); - if (exists) - { - return; - } - - // 2. 构建日志实体与去重记录 - var message = context.Message; - var log = new OperationLog - { - OperationType = message.OperationType, - TargetType = message.TargetType, - TargetIds = message.TargetIds, - OperatorId = message.OperatorId, - OperatorName = message.OperatorName, - Parameters = message.Parameters, - Result = message.Result, - Success = message.Success - }; - logsContext.OperationLogInboxMessages.Add(new OperationLogInboxMessage - { - MessageId = messageId.Value, - ConsumedAt = DateTime.UtcNow - }); - logsContext.OperationLogs.Add(log); - - // 3. 保存并处理并发去重冲突 - try - { - await logsContext.SaveChangesAsync(context.CancellationToken); - } - catch (DbUpdateException ex) when (IsDuplicateMessage(ex)) - { - return; - } - } - - private static bool IsDuplicateMessage(DbUpdateException exception) - { - if (exception.InnerException is PostgresException postgresException) - { - return postgresException.SqlState == PostgresErrorCodes.UniqueViolation; - } - return false; - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Extensions/OperationLogOutboxServiceCollectionExtensions.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Extensions/OperationLogOutboxServiceCollectionExtensions.cs deleted file mode 100644 index 33b452d..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Extensions/OperationLogOutboxServiceCollectionExtensions.cs +++ /dev/null @@ -1,56 +0,0 @@ -using MassTransit; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using TakeoutSaaS.Infrastructure.Identity.Persistence; -using TakeoutSaaS.Infrastructure.Logs.Consumers; -using TakeoutSaaS.Module.Messaging.Options; - -namespace TakeoutSaaS.Infrastructure.Logs.Extensions; - -/// -/// 操作日志 Outbox 注册扩展。 -/// -public static class OperationLogOutboxServiceCollectionExtensions -{ - /// - /// 注册操作日志 Outbox 与消费者。 - /// - /// 服务集合。 - /// 配置源。 - /// 服务集合。 - public static IServiceCollection AddOperationLogOutbox(this IServiceCollection services, IConfiguration configuration) - { - // 1. 读取 RabbitMQ 配置 - var options = configuration.GetSection("RabbitMQ").Get(); - if (options == null) - { - throw new InvalidOperationException("缺少 RabbitMQ 配置。"); - } - - // 2. 注册 MassTransit 与 Outbox - services.AddMassTransit(configurator => - { - configurator.AddConsumer(); - configurator.AddEntityFrameworkOutbox(outbox => - { - outbox.UsePostgres(); - outbox.UseBusOutbox(); - }); - configurator.UsingRabbitMq((context, cfg) => - { - var virtualHost = string.IsNullOrWhiteSpace(options.VirtualHost) ? "/" : options.VirtualHost.Trim(); - var virtualHostPath = virtualHost == "/" ? "/" : $"/{virtualHost.TrimStart('/')}"; - var hostUri = new Uri($"rabbitmq://{options.Host}:{options.Port}{virtualHostPath}"); - cfg.Host(hostUri, host => - { - host.Username(options.Username); - host.Password(options.Password); - }); - cfg.PrefetchCount = options.PrefetchCount; - cfg.ConfigureEndpoints(context); - }); - }); - // 3. 返回服务集合 - return services; - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Persistence/OperationLogInboxMessage.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Persistence/OperationLogInboxMessage.cs deleted file mode 100644 index 8246ced..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Persistence/OperationLogInboxMessage.cs +++ /dev/null @@ -1,19 +0,0 @@ -using TakeoutSaaS.Shared.Abstractions.Entities; - -namespace TakeoutSaaS.Infrastructure.Logs.Persistence; - -/// -/// 操作日志消息消费去重记录。 -/// -public sealed class OperationLogInboxMessage : EntityBase -{ - /// - /// 消息唯一标识。 - /// - public Guid MessageId { get; set; } - - /// - /// 消费时间(UTC)。 - /// - public DateTime ConsumedAt { get; set; } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Persistence/TakeoutLogsDbContext.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Persistence/TakeoutLogsDbContext.cs deleted file mode 100644 index 570c019..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Persistence/TakeoutLogsDbContext.cs +++ /dev/null @@ -1,143 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; -using TakeoutSaaS.Domain.Membership.Entities; -using TakeoutSaaS.Domain.Merchants.Entities; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Infrastructure.Common.Persistence; -using TakeoutSaaS.Shared.Abstractions.Ids; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Infrastructure.Logs.Persistence; - -/// -/// 日志库 DbContext。 -/// -public sealed class TakeoutLogsDbContext( - DbContextOptions options, - ITenantProvider tenantProvider, - ICurrentUserAccessor? currentUserAccessor = null, - IIdGenerator? idGenerator = null) - : TenantAwareDbContext(options, tenantProvider, currentUserAccessor, idGenerator) -{ - /// - /// 租户审计日志集合。 - /// - public DbSet TenantAuditLogs => Set(); - - /// - /// 商户审计日志集合。 - /// - public DbSet MerchantAuditLogs => Set(); - - /// - /// 商户变更日志集合。 - /// - public DbSet MerchantChangeLogs => Set(); - - /// - /// 运营操作日志集合。 - /// - public DbSet OperationLogs => Set(); - - /// - /// 操作日志消息去重集合。 - /// - public DbSet OperationLogInboxMessages => Set(); - - /// - /// 成长值日志集合。 - /// - public DbSet MemberGrowthLogs => Set(); - - /// - /// 配置实体模型。 - /// - /// 模型构建器。 - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - base.OnModelCreating(modelBuilder); - ConfigureTenantAuditLog(modelBuilder.Entity()); - ConfigureMerchantAuditLog(modelBuilder.Entity()); - ConfigureMerchantChangeLog(modelBuilder.Entity()); - ConfigureOperationLog(modelBuilder.Entity()); - ConfigureOperationLogInboxMessage(modelBuilder.Entity()); - ConfigureMemberGrowthLog(modelBuilder.Entity()); - ApplyTenantQueryFilters(modelBuilder); - } - - private static void ConfigureTenantAuditLog(EntityTypeBuilder builder) - { - builder.ToTable("tenant_audit_logs"); - builder.HasKey(x => x.Id); - builder.Property(x => x.TenantId).IsRequired(); - builder.Property(x => x.Title).HasMaxLength(128).IsRequired(); - builder.Property(x => x.Description).HasMaxLength(1024); - builder.Property(x => x.OperatorName).HasMaxLength(64); - builder.HasIndex(x => x.TenantId); - } - - private static void ConfigureMerchantAuditLog(EntityTypeBuilder builder) - { - builder.ToTable("merchant_audit_logs"); - builder.HasKey(x => x.Id); - builder.Property(x => x.MerchantId).IsRequired(); - builder.Property(x => x.Action).HasConversion().IsRequired(); - builder.Property(x => x.Title).HasMaxLength(200).IsRequired(); - builder.Property(x => x.Description).HasMaxLength(1024); - builder.Property(x => x.OperatorName).HasMaxLength(100); - builder.Property(x => x.IpAddress).HasMaxLength(50); - builder.HasIndex(x => new { x.TenantId, x.MerchantId }); - builder.HasIndex(x => new { x.MerchantId, x.CreatedAt }); - builder.HasIndex(x => new { x.TenantId, x.CreatedAt }); - } - - private static void ConfigureMerchantChangeLog(EntityTypeBuilder builder) - { - builder.ToTable("merchant_change_logs"); - builder.HasKey(x => x.Id); - builder.Property(x => x.MerchantId).IsRequired(); - builder.Property(x => x.FieldName).HasMaxLength(100).IsRequired(); - builder.Property(x => x.OldValue).HasColumnType("text"); - builder.Property(x => x.NewValue).HasColumnType("text"); - builder.Property(x => x.ChangeType).HasMaxLength(20).IsRequired(); - builder.Property(x => x.ChangedByName).HasMaxLength(100); - builder.Property(x => x.ChangeReason).HasMaxLength(512); - builder.HasIndex(x => new { x.MerchantId, x.CreatedAt }); - builder.HasIndex(x => new { x.TenantId, x.CreatedAt }); - } - - private static void ConfigureOperationLog(EntityTypeBuilder builder) - { - builder.ToTable("operation_logs"); - builder.HasKey(x => x.Id); - builder.Property(x => x.OperationType).HasMaxLength(64).IsRequired(); - builder.Property(x => x.TargetType).HasMaxLength(64).IsRequired(); - builder.Property(x => x.TargetIds).HasColumnType("text"); - builder.Property(x => x.OperatorId).HasMaxLength(64); - builder.Property(x => x.OperatorName).HasMaxLength(128); - builder.Property(x => x.Parameters).HasColumnType("text"); - builder.Property(x => x.Result).HasColumnType("text"); - builder.Property(x => x.Success).IsRequired(); - builder.HasIndex(x => new { x.OperationType, x.CreatedAt }); - builder.HasIndex(x => x.CreatedAt); - } - - private static void ConfigureOperationLogInboxMessage(EntityTypeBuilder builder) - { - builder.ToTable("operation_log_inbox_messages"); - builder.HasKey(x => x.Id); - builder.Property(x => x.MessageId).IsRequired(); - builder.Property(x => x.ConsumedAt).IsRequired(); - builder.HasIndex(x => x.MessageId).IsUnique(); - } - - private static void ConfigureMemberGrowthLog(EntityTypeBuilder builder) - { - builder.ToTable("member_growth_logs"); - builder.HasKey(x => x.Id); - builder.Property(x => x.MemberId).IsRequired(); - builder.Property(x => x.Notes).HasMaxLength(256); - builder.HasIndex(x => new { x.TenantId, x.MemberId, x.OccurredAt }); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Persistence/TakeoutLogsDesignTimeDbContextFactory.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Persistence/TakeoutLogsDesignTimeDbContextFactory.cs deleted file mode 100644 index 5184dcf..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Persistence/TakeoutLogsDesignTimeDbContextFactory.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Infrastructure.Common.Persistence.DesignTime; -using TakeoutSaaS.Shared.Abstractions.Constants; -using TakeoutSaaS.Shared.Abstractions.Security; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Infrastructure.Logs.Persistence; - -/// -/// 日志库设计时工厂,供 EF CLI 使用。 -/// -internal sealed class TakeoutLogsDesignTimeDbContextFactory - : DesignTimeDbContextFactoryBase -{ - /// - /// 初始化日志库设计时上下文工厂。 - /// - public TakeoutLogsDesignTimeDbContextFactory() - : base(DatabaseConstants.LogsDataSource, "TAKEOUTSAAS_LOGS_CONNECTION") - { - } - - /// - /// 创建日志库 DbContext。 - /// - /// 上下文选项。 - /// 租户提供器。 - /// 当前用户访问器。 - /// 日志库上下文实例。 - protected override TakeoutLogsDbContext CreateContext( - DbContextOptions options, - ITenantProvider tenantProvider, - ICurrentUserAccessor currentUserAccessor) - => new(options, tenantProvider, currentUserAccessor); -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Publishers/IdentityOperationLogPublisher.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Publishers/IdentityOperationLogPublisher.cs deleted file mode 100644 index 918f5a9..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Publishers/IdentityOperationLogPublisher.cs +++ /dev/null @@ -1,27 +0,0 @@ -using MassTransit; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.Identity.Abstractions; -using TakeoutSaaS.Application.Identity.Events; - -namespace TakeoutSaaS.Infrastructure.Logs.Publishers; - -/// -/// 身份模块操作日志发布器(基于 MassTransit Outbox)。 -/// -public sealed class IdentityOperationLogPublisher( - ILogger logger, - IPublishEndpoint? publishEndpoint = null) : IIdentityOperationLogPublisher -{ - /// - public Task PublishAsync(IdentityUserOperationLogMessage message, CancellationToken cancellationToken = default) - { - if (publishEndpoint is null) - { - logger.LogDebug("未配置 MassTransit,已跳过操作日志消息发布:{OperationType}", message.OperationType); - return Task.CompletedTask; - } - - // 1. (空行后) 已配置 MassTransit 时正常发布消息 - return publishEndpoint.Publish(message, cancellationToken); - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Repositories/EfOperationLogRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Repositories/EfOperationLogRepository.cs deleted file mode 100644 index 80b5643..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Repositories/EfOperationLogRepository.cs +++ /dev/null @@ -1,63 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using TakeoutSaaS.Domain.Tenants.Entities; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Infrastructure.Logs.Persistence; - -namespace TakeoutSaaS.Infrastructure.Logs.Repositories; - -/// -/// 运营操作日志仓储实现。 -/// -public sealed class EfOperationLogRepository(TakeoutLogsDbContext logsContext) : IOperationLogRepository -{ - /// - public async Task<(IReadOnlyList Items, int Total)> SearchByOperatorPagedAsync( - long tenantId, - string operatorId, - DateTime from, - DateTime to, - int page, - int pageSize, - CancellationToken cancellationToken = default) - { - // 1. 归一化参数 - var normalizedOperatorId = operatorId.Trim(); - var normalizedPage = page <= 0 ? 1 : page; - var normalizedPageSize = pageSize <= 0 ? 50 : pageSize; - - // 2. 构建查询(操作人 + 时间窗 + 租户约束) - var query = logsContext.OperationLogs - .AsNoTracking() - .Where(x => x.DeletedAt == null - && x.OperatorId == normalizedOperatorId - && x.CreatedAt >= from - && x.CreatedAt <= to - && x.Parameters != null - && (EF.Functions.ILike(x.Parameters, $"%\"tenantId\":{tenantId}%") - || EF.Functions.ILike(x.Parameters, $"%\"TenantId\":{tenantId}%"))); - - // 3. 查询总数与分页项 - var total = await query.CountAsync(cancellationToken); - var items = await query - .OrderByDescending(x => x.CreatedAt) - .Skip((normalizedPage - 1) * normalizedPageSize) - .Take(normalizedPageSize) - .ToListAsync(cancellationToken); - - // 4. 返回分页结果 - return (items, total); - } - - /// - public Task AddAsync(OperationLog log, CancellationToken cancellationToken = default) - { - // 1. 添加日志实体 - logsContext.OperationLogs.Add(log); - // 2. 返回完成任务 - return Task.CompletedTask; - } - - /// - public Task SaveChangesAsync(CancellationToken cancellationToken = default) - => logsContext.SaveChangesAsync(cancellationToken); -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251202005208_InitSnowflake_App.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251202005208_InitSnowflake_App.Designer.cs deleted file mode 100644 index 84faa52..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251202005208_InitSnowflake_App.Designer.cs +++ /dev/null @@ -1,5799 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.App.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - [DbContext(typeof(TakeoutAppDbContext))] - [Migration("20251202005208_InitSnowflake_App")] - partial class InitSnowflake_App - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricAlertRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionJson") - .IsRequired() - .HasColumnType("text") - .HasComment("触发条件 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Enabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("关联指标。"); - - b.Property("NotificationChannels") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("通知渠道。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("告警级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "Severity"); - - b.ToTable("metric_alert_rules", null, t => - { - t.HasComment("指标告警规则。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricDefinition", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("指标编码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultAggregation") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("默认聚合方式。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("说明。"); - - b.Property("DimensionsJson") - .HasColumnType("text") - .HasComment("维度描述 JSON。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("指标名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("metric_definitions", null, t => - { - t.HasComment("指标定义,描述可观测的数据点。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricSnapshot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DimensionKey") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("维度键(JSON)。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("指标定义 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Value") - .HasPrecision(18, 4) - .HasColumnType("numeric(18,4)") - .HasComment("数值。"); - - b.Property("WindowEnd") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口结束。"); - - b.Property("WindowStart") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口开始。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "DimensionKey", "WindowStart", "WindowEnd") - .IsUnique(); - - b.ToTable("metric_snapshots", null, t => - { - t.HasComment("指标快照,用于大盘展示。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.Coupon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("券码或序列号。"); - - b.Property("CouponTemplateId") - .HasColumnType("bigint") - .HasComment("模板标识。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("发放时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID(已使用时记录)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedAt") - .HasColumnType("timestamp with time zone") - .HasComment("使用时间。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("归属用户。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("coupons", null, t => - { - t.HasComment("用户领取的券。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.CouponTemplate", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowStack") - .HasColumnType("boolean") - .HasComment("是否允许叠加其他优惠。"); - - b.Property("ChannelsJson") - .HasColumnType("text") - .HasComment("发放渠道(JSON)。"); - - b.Property("ClaimedQuantity") - .HasColumnType("integer") - .HasComment("已领取数量。"); - - b.Property("CouponType") - .HasColumnType("integer") - .HasComment("券类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("DiscountCap") - .HasColumnType("numeric") - .HasComment("折扣上限(针对折扣券)。"); - - b.Property("MinimumSpend") - .HasColumnType("numeric") - .HasComment("最低消费门槛。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("模板名称。"); - - b.Property("ProductScopeJson") - .HasColumnType("text") - .HasComment("适用品类或商品范围(JSON)。"); - - b.Property("RelativeValidDays") - .HasColumnType("integer") - .HasComment("有效天数(相对发放时间)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreScopeJson") - .HasColumnType("text") - .HasComment("适用门店 ID 集合(JSON)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TotalQuantity") - .HasColumnType("integer") - .HasComment("总发放数量上限。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ValidFrom") - .HasColumnType("timestamp with time zone") - .HasComment("可用开始时间。"); - - b.Property("ValidTo") - .HasColumnType("timestamp with time zone") - .HasComment("可用结束时间。"); - - b.Property("Value") - .HasColumnType("numeric") - .HasComment("面值或折扣额度。"); - - b.HasKey("Id"); - - b.ToTable("coupon_templates", null, t => - { - t.HasComment("优惠券模板。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.PromotionCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AudienceDescription") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("目标人群描述。"); - - b.Property("BannerUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营销素材(如 banner)。"); - - b.Property("Budget") - .HasColumnType("numeric") - .HasComment("预算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("PromotionType") - .HasColumnType("integer") - .HasComment("活动类型。"); - - b.Property("RulesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("活动规则 JSON。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("活动状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("promotion_campaigns", null, t => - { - t.HasComment("营销活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChatSessionId") - .HasColumnType("bigint") - .HasComment("会话标识。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("消息内容。"); - - b.Property("ContentType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("消息类型(文字/图片/语音等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRead") - .HasColumnType("boolean") - .HasComment("是否已读。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("读取时间。"); - - b.Property("SenderType") - .HasColumnType("integer") - .HasComment("发送方类型。"); - - b.Property("SenderUserId") - .HasColumnType("bigint") - .HasComment("发送方用户 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ChatSessionId", "CreatedAt"); - - b.ToTable("chat_messages", null, t => - { - t.HasComment("会话消息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AgentUserId") - .HasColumnType("bigint") - .HasComment("当前客服员工 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("顾客用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndedAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("IsBotActive") - .HasColumnType("boolean") - .HasComment("是否机器人接待中。"); - - b.Property("SessionCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话编号。"); - - b.Property("StartedAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店(可空为平台)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionCode") - .IsUnique(); - - b.ToTable("chat_sessions", null, t => - { - t.HasComment("客服会话。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.SupportTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AssignedAgentId") - .HasColumnType("bigint") - .HasComment("指派的客服。"); - - b.Property("ClosedAt") - .HasColumnType("timestamp with time zone") - .HasComment("关闭时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("客户用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .IsRequired() - .HasColumnType("text") - .HasComment("工单详情。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单(如有)。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("优先级。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("Subject") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("工单主题。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("工单编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TicketNo") - .IsUnique(); - - b.ToTable("support_tickets", null, t => - { - t.HasComment("客服工单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.TicketComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttachmentsJson") - .HasColumnType("text") - .HasComment("附件 JSON。"); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人 ID。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsInternal") - .HasColumnType("boolean") - .HasComment("是否内部备注。"); - - b.Property("SupportTicketId") - .HasColumnType("bigint") - .HasComment("工单标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SupportTicketId"); - - b.ToTable("ticket_comments", null, t => - { - t.HasComment("工单评论/流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryEvent", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryOrderId") - .HasColumnType("bigint") - .HasComment("配送单标识。"); - - b.Property("EventType") - .HasColumnType("integer") - .HasComment("事件类型。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("事件描述。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始数据 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DeliveryOrderId", "EventType"); - - b.ToTable("delivery_events", null, t => - { - t.HasComment("配送状态事件流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CourierName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("骑手姓名。"); - - b.Property("CourierPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("骑手电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveredAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("DispatchedAt") - .HasColumnType("timestamp with time zone") - .HasComment("下发时间。"); - - b.Property("FailureReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("异常原因。"); - - b.Property("OrderId") - .HasColumnType("bigint"); - - b.Property("PickedUpAt") - .HasColumnType("timestamp with time zone") - .HasComment("取餐时间。"); - - b.Property("Provider") - .HasColumnType("integer") - .HasComment("配送服务商。"); - - b.Property("ProviderOrderId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方配送单号。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId") - .IsUnique(); - - b.ToTable("delivery_orders", null, t => - { - t.HasComment("配送单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliateOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("推广人标识。"); - - b.Property("BuyerUserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedCommission") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("预计佣金。"); - - b.Property("OrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("订单金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("SettledAt") - .HasColumnType("timestamp with time zone") - .HasComment("结算完成时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "OrderId") - .IsUnique(); - - b.ToTable("affiliate_orders", null, t => - { - t.HasComment("分销订单记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePartner", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChannelType") - .HasColumnType("integer") - .HasComment("渠道类型。"); - - b.Property("CommissionRate") - .HasColumnType("numeric") - .HasComment("分成比例(0-1)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称或渠道名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID(如绑定平台账号)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DisplayName"); - - b.ToTable("affiliate_partners", null, t => - { - t.HasComment("分销/推广合作伙伴。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePayout", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("合作伙伴标识。"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("结算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("打款时间。"); - - b.Property("Period") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("结算周期描述。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "Period") - .IsUnique(); - - b.ToTable("affiliate_payouts", null, t => - { - t.HasComment("佣金结算记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowMakeupCount") - .HasColumnType("integer") - .HasComment("支持补签次数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("活动描述。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("结束日期。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("RewardsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("连签奖励 JSON。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("开始日期。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name"); - - b.ToTable("checkin_campaigns", null, t => - { - t.HasComment("签到活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CheckInCampaignId") - .HasColumnType("bigint") - .HasComment("活动标识。"); - - b.Property("CheckInDate") - .HasColumnType("timestamp with time zone") - .HasComment("签到日期(本地)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsMakeup") - .HasColumnType("boolean") - .HasComment("是否补签。"); - - b.Property("RewardJson") - .IsRequired() - .HasColumnType("text") - .HasComment("获得奖励 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "CheckInCampaignId", "UserId", "CheckInDate") - .IsUnique(); - - b.ToTable("checkin_records", null, t => - { - t.HasComment("用户签到记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsDeleted") - .HasColumnType("boolean") - .HasComment("状态。"); - - b.Property("ParentId") - .HasColumnType("bigint") - .HasComment("父级评论 ID。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "CreatedAt"); - - b.ToTable("community_comments", null, t => - { - t.HasComment("社区评论。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityPost", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("作者用户 ID。"); - - b.Property("CommentCount") - .HasColumnType("integer") - .HasComment("评论数。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LikeCount") - .HasColumnType("integer") - .HasComment("点赞数。"); - - b.Property("MediaJson") - .HasColumnType("text") - .HasComment("媒体资源 JSON。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AuthorUserId", "CreatedAt"); - - b.ToTable("community_posts", null, t => - { - t.HasComment("社区动态。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityReaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态 ID。"); - - b.Property("ReactedAt") - .HasColumnType("timestamp with time zone") - .HasComment("时间戳。"); - - b.Property("ReactionType") - .HasColumnType("integer") - .HasComment("反应类型。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "UserId") - .IsUnique(); - - b.ToTable("community_reactions", null, t => - { - t.HasComment("社区互动反馈。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentCount") - .HasColumnType("integer") - .HasComment("当前已参与人数。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("GroupOrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("拼单编号。"); - - b.Property("GroupPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("拼团价格。"); - - b.Property("LeaderUserId") - .HasColumnType("bigint") - .HasComment("团长用户 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("关联商品或套餐。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("拼团状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("SucceededAt") - .HasColumnType("timestamp with time zone") - .HasComment("成团时间。"); - - b.Property("TargetCount") - .HasColumnType("integer") - .HasComment("成团需要的人数。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderNo") - .IsUnique(); - - b.ToTable("group_orders", null, t => - { - t.HasComment("拼单活动。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupParticipant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GroupOrderId") - .HasColumnType("bigint") - .HasComment("拼单活动标识。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("参与时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("对应订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("参与状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderId", "UserId") - .IsUnique(); - - b.ToTable("group_participants", null, t => - { - t.HasComment("拼单参与者。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryAdjustment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdjustmentType") - .HasColumnType("integer") - .HasComment("调整类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("InventoryItemId") - .HasColumnType("bigint") - .HasComment("对应的库存记录标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("调整数量,正数增加,负数减少。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("原因说明。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "InventoryItemId", "OccurredAt"); - - b.ToTable("inventory_adjustments", null, t => - { - t.HasComment("库存调整记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryBatch", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("ProductionDate") - .HasColumnType("timestamp with time zone") - .HasComment("生产日期。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("入库数量。"); - - b.Property("RemainingQuantity") - .HasColumnType("integer") - .HasComment("剩余数量。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber") - .IsUnique(); - - b.ToTable("inventory_batches", null, t => - { - t.HasComment("SKU 批次信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号,可为空表示混批。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("Location") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("储位或仓位信息。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("QuantityOnHand") - .HasColumnType("integer") - .HasComment("可用库存。"); - - b.Property("QuantityReserved") - .HasColumnType("integer") - .HasComment("已锁定库存(订单占用)。"); - - b.Property("SafetyStock") - .HasColumnType("integer") - .HasComment("安全库存阈值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber"); - - b.ToTable("inventory_items", null, t => - { - t.HasComment("SKU 在门店的库存信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberGrowthLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChangeValue") - .HasColumnType("integer") - .HasComment("变动数量。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentValue") - .HasColumnType("integer") - .HasComment("当前成长值。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_growth_logs", null, t => - { - t.HasComment("成长值变动日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberPointLedger", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BalanceAfterChange") - .HasColumnType("integer") - .HasComment("变动后余额。"); - - b.Property("ChangeAmount") - .HasColumnType("integer") - .HasComment("变动数量,可为负值。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(如适用)。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Reason") - .HasColumnType("integer") - .HasComment("变动原因。"); - - b.Property("SourceId") - .HasColumnType("bigint") - .HasComment("来源 ID(订单、活动等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_point_ledgers", null, t => - { - t.HasComment("积分变动流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AvatarUrl") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像。"); - - b.Property("BirthDate") - .HasColumnType("timestamp with time zone") - .HasComment("生日。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GrowthValue") - .HasColumnType("integer") - .HasComment("成长值/经验值。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("注册时间。"); - - b.Property("MemberTierId") - .HasColumnType("bigint") - .HasComment("当前会员等级 ID。"); - - b.Property("Mobile") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("Nickname") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称。"); - - b.Property("PointsBalance") - .HasColumnType("integer") - .HasComment("会员积分余额。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会员状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Mobile") - .IsUnique(); - - b.ToTable("member_profiles", null, t => - { - t.HasComment("会员档案。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberTier", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BenefitsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("等级权益(JSON)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("等级名称。"); - - b.Property("RequiredGrowth") - .HasColumnType("integer") - .HasComment("所需成长值。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("member_tiers", null, t => - { - t.HasComment("会员等级定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.Merchant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("BrandAlias") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("品牌简称或别名。"); - - b.Property("BrandName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("品牌名称(对外展示)。"); - - b.Property("BusinessLicenseImageUrl") - .HasColumnType("text") - .HasComment("营业执照扫描件地址。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照号。"); - - b.Property("Category") - .HasColumnType("text") - .HasComment("品牌所属品类,如火锅、咖啡等。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("联系邮箱。"); - - b.Property("ContactPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在区县。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("入驻时间。"); - - b.Property("LastReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次审核时间。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度信息。"); - - b.Property("LegalPerson") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人或负责人姓名。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("品牌 Logo。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度信息。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注或驳回原因。"); - - b.Property("ServicePhone") - .HasColumnType("text") - .HasComment("客服电话。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("入驻状态。"); - - b.Property("SupportEmail") - .HasColumnType("text") - .HasComment("客服邮箱。"); - - b.Property("TaxNumber") - .HasColumnType("text") - .HasComment("税号/统一社会信用代码。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.ToTable("merchants", null, t => - { - t.HasComment("商户主体信息,承载入驻和资质审核结果。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantContract", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ContractNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("合同编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同结束时间。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("合同文件存储地址。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("SignedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签署时间。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("合同状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TerminatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("终止时间。"); - - b.Property("TerminationReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("终止原因。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "ContractNumber") - .IsUnique(); - - b.ToTable("merchant_contracts", null, t => - { - t.HasComment("商户合同记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantDocument", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DocumentNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("证照编号。"); - - b.Property("DocumentType") - .HasColumnType("integer") - .HasComment("证照类型。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期日期。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("证照文件链接。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签发日期。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Remarks") - .HasColumnType("text") - .HasComment("审核备注或驳回原因。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("审核状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "DocumentType"); - - b.ToTable("merchant_documents", null, t => - { - t.HasComment("商户提交的资质或证照材料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantStaff", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Email") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("邮箱地址。"); - - b.Property("IdentityUserId") - .HasColumnType("bigint") - .HasComment("登录账号 ID(指向统一身份体系)。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("员工姓名。"); - - b.Property("PermissionsJson") - .HasColumnType("text") - .HasComment("自定义权限(JSON)。"); - - b.Property("Phone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("员工角色类型。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("员工状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("可选的关联门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "Phone"); - - b.ToTable("merchant_staff", null, t => - { - t.HasComment("商户员工账号,支持门店维度分配。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.MapLocation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Landmark") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("打车/导航落点描述。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("名称。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店 ID,可空表示独立 POI。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("map_locations", null, t => - { - t.HasComment("地图 POI 信息,用于门店定位和推荐。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.NavigationRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("来源通道(小程序、H5 等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("请求时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TargetApp") - .HasColumnType("integer") - .HasComment("跳转的地图应用。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId", "RequestedAt"); - - b.ToTable("navigation_requests", null, t => - { - t.HasComment("用户发起的导航请求日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("扩展 JSON(规格、加料选项等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品或 SKU 标识。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称快照。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("自定义备注(口味要求)。"); - - b.Property("ShoppingCartId") - .HasColumnType("bigint") - .HasComment("所属购物车标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价快照。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ShoppingCartId"); - - b.ToTable("cart_items", null, t => - { - t.HasComment("购物车条目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItemAddon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CartItemId") - .HasColumnType("bigint") - .HasComment("所属购物车条目。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("OptionId") - .HasColumnType("bigint") - .HasComment("选项 ID(可对应 ProductAddonOption)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("cart_item_addons", null, t => - { - t.HasComment("购物车条目的加料/附加项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CheckoutSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("SessionToken") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话 Token。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.Property("ValidationResultJson") - .IsRequired() - .HasColumnType("text") - .HasComment("校验结果明细 JSON。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionToken") - .IsUnique(); - - b.ToTable("checkout_sessions", null, t => - { - t.HasComment("结账会话,记录校验上下文。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.ShoppingCart", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryPreference") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("履约方式(堂食/自提/配送)缓存。"); - - b.Property("LastModifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次修改时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("购物车状态,包含正常/锁定。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableContext") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌码或场景标识(扫码点餐)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId") - .IsUnique(); - - b.ToTable("shopping_carts", null, t => - { - t.HasComment("用户购物车,按租户/门店隔离。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.Order", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("取消原因。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("下单渠道。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("顾客姓名。"); - - b.Property("CustomerPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("顾客手机号。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryType") - .HasColumnType("integer") - .HasComment("履约类型。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("优惠金额。"); - - b.Property("FinishedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("ItemsAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("商品总额。"); - - b.Property("OrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("订单号。"); - - b.Property("PaidAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付时间。"); - - b.Property("PayableAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额。"); - - b.Property("PaymentStatus") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("QueueNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队号(如有)。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationId") - .HasColumnType("bigint") - .HasComment("预约 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TableNo") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("就餐桌号。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "Status"); - - b.ToTable("orders", null, t => - { - t.HasComment("交易订单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("自定义属性 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("折扣金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品 ID。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("SkuName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("SKU/规格描述。"); - - b.Property("SubTotal") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("小计。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("单位。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("OrderId"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("order_items", null, t => - { - t.HasComment("订单明细。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderStatusHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注信息。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识(可为空表示系统)。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("变更后的状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId", "OccurredAt"); - - b.ToTable("order_status_histories", null, t => - { - t.HasComment("订单状态流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.RefundRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("申请金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("ProcessedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核完成时间。"); - - b.Property("Reason") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("申请原因。"); - - b.Property("RefundNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("退款单号。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("用户提交时间。"); - - b.Property("ReviewNotes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "RefundNo") - .IsUnique(); - - b.ToTable("refund_requests", null, t => - { - t.HasComment("售后/退款申请。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("支付金额。"); - - b.Property("ChannelTransactionId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方渠道单号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Method") - .HasColumnType("integer") - .HasComment("支付方式。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付完成时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始回调内容。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("错误/备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TradeNo") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("平台交易号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("payment_records", null, t => - { - t.HasComment("支付流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRefundRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("退款金额。"); - - b.Property("ChannelRefundId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("渠道退款流水号。"); - - b.Property("CompletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("渠道返回的原始数据 JSON。"); - - b.Property("PaymentRecordId") - .HasColumnType("bigint") - .HasComment("原支付记录标识。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("退款请求时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PaymentRecordId"); - - b.ToTable("payment_refund_records", null, t => - { - t.HasComment("支付渠道退款流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.Product", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CategoryId") - .HasColumnType("bigint") - .HasComment("所属分类。"); - - b.Property("CoverImage") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("主图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("商品描述。"); - - b.Property("EnableDelivery") - .HasColumnType("boolean") - .HasComment("支持配送。"); - - b.Property("EnableDineIn") - .HasColumnType("boolean") - .HasComment("支持堂食。"); - - b.Property("EnablePickup") - .HasColumnType("boolean") - .HasComment("支持自提。"); - - b.Property("GalleryImages") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Gallery 图片逗号分隔。"); - - b.Property("IsFeatured") - .HasColumnType("boolean") - .HasComment("是否热门推荐。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("最大每单限购。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("现价。"); - - b.Property("SpuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("商品编码。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("商品状态。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("库存数量(可选)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("Subtitle") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("副标题/卖点。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("售卖单位(份/杯等)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SpuCode") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("products", null, t => - { - t.HasComment("商品(SPU)信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("MaxSelect") - .HasColumnType("integer") - .HasComment("最大选择数量。"); - - b.Property("MinSelect") - .HasColumnType("integer") - .HasComment("最小选择数量。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "Name"); - - b.ToTable("product_addon_groups", null, t => - { - t.HasComment("加料/做法分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AddonGroupId") - .HasColumnType("bigint") - .HasComment("所属加料分组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选项。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("product_addon_options", null, t => - { - t.HasComment("加料选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称,例如“辣度”“份量”。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型(单选/多选)。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("显示排序。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店,可为空表示所有门店共享。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("product_attribute_groups", null, t => - { - t.HasComment("商品规格/属性分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributeGroupId") - .HasColumnType("bigint") - .HasComment("所属规格组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选中。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AttributeGroupId", "Name") - .IsUnique(); - - b.ToTable("product_attribute_options", null, t => - { - t.HasComment("商品规格选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("分类描述。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分类名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("product_categories", null, t => - { - t.HasComment("商品分类。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductMediaAsset", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Caption") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述或标题。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MediaType") - .HasColumnType("integer") - .HasComment("媒体类型。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品标识。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Url") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("媒资链接。"); - - b.HasKey("Id"); - - b.ToTable("product_media_assets", null, t => - { - t.HasComment("商品媒资素材。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductPricingRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("条件描述(JSON),如会员等级、渠道等。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效结束时间。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("特殊价格。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("RuleType") - .HasColumnType("integer") - .HasComment("策略类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StartTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效开始时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("WeekdaysJson") - .HasColumnType("text") - .HasComment("生效星期(JSON 数组)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "RuleType"); - - b.ToTable("product_pricing_rules", null, t => - { - t.HasComment("商品价格策略,支持会员价/时段价等。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductSku", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("规格属性 JSON(记录选项 ID)。"); - - b.Property("Barcode") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("条形码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("售价。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SkuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("SKU 编码。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("可售库存。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weight") - .HasPrecision(10, 3) - .HasColumnType("numeric(10,3)") - .HasComment("重量(千克)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SkuCode") - .IsUnique(); - - b.ToTable("product_skus", null, t => - { - t.HasComment("商品 SKU,记录具体规格组合价格。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Queues.Entities.QueueTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CalledAt") - .HasColumnType("timestamp with time zone") - .HasComment("叫号时间。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedWaitMinutes") - .HasColumnType("integer") - .HasComment("预计等待分钟。"); - - b.Property("ExpiredAt") - .HasColumnType("timestamp with time zone") - .HasComment("过号时间。"); - - b.Property("PartySize") - .HasColumnType("integer") - .HasComment("就餐人数。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNumber") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.HasIndex("TenantId", "StoreId", "TicketNumber") - .IsUnique(); - - b.ToTable("queue_tickets", null, t => - { - t.HasComment("排队叫号。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Reservations.Entities.Reservation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CheckInCode") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("核销码/到店码。"); - - b.Property("CheckedInAt") - .HasColumnType("timestamp with time zone") - .HasComment("实际签到时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("客户姓名。"); - - b.Property("CustomerPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PeopleCount") - .HasColumnType("integer") - .HasComment("用餐人数。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("预约号。"); - - b.Property("ReservationTime") - .HasColumnType("timestamp with time zone") - .HasComment("预约时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TablePreference") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌型/标签。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ReservationNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("reservations", null, t => - { - t.HasComment("预约/预订记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.Store", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("Announcement") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("门店公告。"); - - b.Property("BusinessHours") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("门店营业时段描述(备用字符串)。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("门店编码,便于扫码及外部对接。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家或地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("门店海报。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryRadiusKm") - .HasPrecision(6, 2) - .HasColumnType("numeric(6,2)") - .HasComment("默认配送半径(公里)。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("门店描述或公告。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区县信息。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("高德/腾讯地图经度。"); - - b.Property("ManagerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("门店负责人姓名。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("门店名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("门店当前运营状态。"); - - b.Property("SupportsDelivery") - .HasColumnType("boolean") - .HasComment("是否支持配送。"); - - b.Property("SupportsDineIn") - .HasColumnType("boolean") - .HasComment("是否支持堂食。"); - - b.Property("SupportsPickup") - .HasColumnType("boolean") - .HasComment("是否支持自提。"); - - b.Property("SupportsQueueing") - .HasColumnType("boolean") - .HasComment("支持排队叫号。"); - - b.Property("SupportsReservation") - .HasColumnType("boolean") - .HasComment("支持预约。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("门店标签(逗号分隔)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.HasIndex("TenantId", "MerchantId"); - - b.ToTable("stores", null, t => - { - t.HasComment("门店信息,承载营业配置与能力。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreBusinessHour", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CapacityLimit") - .HasColumnType("integer") - .HasComment("最大接待容量或单量限制。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DayOfWeek") - .HasColumnType("integer") - .HasComment("星期几,0 表示周日。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间(本地时间)。"); - - b.Property("HourType") - .HasColumnType("integer") - .HasComment("时段类型(正常营业、休息、预约等)。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间(本地时间)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "DayOfWeek"); - - b.ToTable("store_business_hours", null, t => - { - t.HasComment("门店营业时段配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreDeliveryZone", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("EstimatedMinutes") - .HasColumnType("integer") - .HasComment("预计送达分钟。"); - - b.Property("MinimumOrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("起送价。"); - - b.Property("PolygonGeoJson") - .IsRequired() - .HasColumnType("text") - .HasComment("GeoJSON 表示的多边形范围。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ZoneName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ZoneName"); - - b.ToTable("store_delivery_zones", null, t => - { - t.HasComment("门店配送范围配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreEmployeeShift", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("排班角色。"); - - b.Property("ShiftDate") - .HasColumnType("timestamp with time zone") - .HasComment("班次日期。"); - - b.Property("StaffId") - .HasColumnType("bigint") - .HasComment("员工标识。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ShiftDate", "StaffId") - .IsUnique(); - - b.ToTable("store_employee_shifts", null, t => - { - t.HasComment("门店员工排班记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreHoliday", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Date") - .HasColumnType("timestamp with time zone") - .HasComment("日期。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsClosed") - .HasColumnType("boolean") - .HasComment("是否全天闭店。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("说明内容。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Date") - .IsUnique(); - - b.ToTable("store_holidays", null, t => - { - t.HasComment("门店休息日或特殊营业日。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTable", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AreaId") - .HasColumnType("bigint") - .HasComment("所在区域 ID。"); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("可容纳人数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("QrCodeUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("桌码二维码地址。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前桌台状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("桌码。"); - - b.Property("Tags") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("桌台标签(堂食、快餐等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "TableCode") - .IsUnique(); - - b.ToTable("store_tables", null, t => - { - t.HasComment("桌台信息与二维码绑定。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTableArea", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("区域描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name") - .IsUnique(); - - b.ToTable("store_table_areas", null, t => - { - t.HasComment("门店桌台区域配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.Tenant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("text") - .HasComment("详细地址信息。"); - - b.Property("City") - .HasColumnType("text") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("租户短编码,作为跨系统引用的唯一标识。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("主联系人邮箱。"); - - b.Property("ContactName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("主联系人姓名。"); - - b.Property("ContactPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("主联系人电话。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家/地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("品牌海报或封面图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("服务生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("服务到期时间(UTC)。"); - - b.Property("Industry") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所属行业,如餐饮、零售等。"); - - b.Property("LegalEntityName") - .HasColumnType("text") - .HasComment("法人或公司主体名称。"); - - b.Property("LogoUrl") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("LOGO 图片地址。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("租户全称或品牌名称。"); - - b.Property("PrimaryOwnerUserId") - .HasColumnType("bigint") - .HasComment("系统内对应的租户所有者账号 ID。"); - - b.Property("Province") - .HasColumnType("text") - .HasComment("所在省份或州。"); - - b.Property("Remarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息,用于运营记录特殊说明。"); - - b.Property("ShortName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("对外展示的简称。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("租户当前状态,涵盖审核、启用、停用等场景。"); - - b.Property("SuspendedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次暂停服务时间。"); - - b.Property("SuspensionReason") - .HasColumnType("text") - .HasComment("暂停或终止的原因说明。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("业务标签集合(逗号分隔)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Website") - .HasColumnType("text") - .HasComment("官网或主要宣传链接。"); - - b.HasKey("Id"); - - b.HasIndex("Code") - .IsUnique(); - - b.ToTable("tenants", null, t => - { - t.HasComment("平台租户信息,描述租户的生命周期与基础资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantBillingStatement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AmountDue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额。"); - - b.Property("AmountPaid") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DueDate") - .HasColumnType("timestamp with time zone") - .HasComment("到期日。"); - - b.Property("LineItemsJson") - .HasColumnType("text") - .HasComment("账单明细 JSON,记录各项费用。"); - - b.Property("PeriodEnd") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期结束时间。"); - - b.Property("PeriodStart") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期开始时间。"); - - b.Property("StatementNo") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("账单编号,供对账查询。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前付款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StatementNo") - .IsUnique(); - - b.ToTable("tenant_billing_statements", null, t => - { - t.HasComment("租户账单,用于呈现周期性收费。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantNotification", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("发布通道(站内、邮件、短信等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("通知正文。"); - - b.Property("MetadataJson") - .HasColumnType("text") - .HasComment("附加元数据 JSON。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("租户是否已阅读。"); - - b.Property("SentAt") - .HasColumnType("timestamp with time zone") - .HasComment("推送时间。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("通知重要级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("通知标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Channel", "SentAt"); - - b.ToTable("tenant_notifications", null, t => - { - t.HasComment("面向租户的站内通知或消息推送。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantPackage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("套餐描述,包含适用场景、权益等。"); - - b.Property("FeaturePoliciesJson") - .HasColumnType("text") - .HasComment("权益明细 JSON,记录自定义特性开关。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否仍可售卖。"); - - b.Property("MaxAccountCount") - .HasColumnType("integer") - .HasComment("允许创建的最大账号数。"); - - b.Property("MaxDeliveryOrders") - .HasColumnType("integer") - .HasComment("每月可调用的配送单数量上限。"); - - b.Property("MaxSmsCredits") - .HasColumnType("integer") - .HasComment("每月短信额度上限。"); - - b.Property("MaxStorageGb") - .HasColumnType("integer") - .HasComment("存储容量上限(GB)。"); - - b.Property("MaxStoreCount") - .HasColumnType("integer") - .HasComment("允许的最大门店数。"); - - b.Property("MonthlyPrice") - .HasColumnType("numeric") - .HasComment("月付价格,单位:人民币元。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("套餐名称,展示给租户的简称。"); - - b.Property("PackageType") - .HasColumnType("integer") - .HasComment("套餐分类(试用、标准、旗舰等)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("YearlyPrice") - .HasColumnType("numeric") - .HasComment("年付价格,单位:人民币元。"); - - b.HasKey("Id"); - - b.ToTable("tenant_packages", null, t => - { - t.HasComment("平台提供的租户套餐定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaUsage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LastResetAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次重置时间。"); - - b.Property("LimitValue") - .HasColumnType("numeric") - .HasComment("当前配额上限。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型,例如门店数、短信条数等。"); - - b.Property("ResetCycle") - .HasColumnType("text") - .HasComment("配额刷新周期描述(如月、年)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedValue") - .HasColumnType("numeric") - .HasComment("已消耗的数量。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "QuotaType") - .IsUnique(); - - b.ToTable("tenant_quota_usages", null, t => - { - t.HasComment("租户配额使用情况快照。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscription", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AutoRenew") - .HasColumnType("boolean") - .HasComment("是否开启自动续费。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("订阅生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("订阅到期时间(UTC)。"); - - b.Property("NextBillingDate") - .HasColumnType("timestamp with time zone") - .HasComment("下一个计费时间,配合自动续费使用。"); - - b.Property("Notes") - .HasColumnType("text") - .HasComment("运营备注信息。"); - - b.Property("ScheduledPackageId") - .HasColumnType("bigint") - .HasComment("若已排期升降配,对应的新套餐 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("订阅当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TenantPackageId") - .HasColumnType("bigint") - .HasComment("当前订阅关联的套餐标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantPackageId"); - - b.ToTable("tenant_subscriptions", null, t => - { - t.HasComment("租户套餐订阅记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.HasOne("TakeoutSaaS.Domain.Orders.Entities.Order", null) - .WithMany() - .HasForeignKey("OrderId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251202005208_InitSnowflake_App.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251202005208_InitSnowflake_App.cs deleted file mode 100644 index 6e26a56..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251202005208_InitSnowflake_App.cs +++ /dev/null @@ -1,2549 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - /// - public partial class InitSnowflake_App : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "affiliate_orders", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - AffiliatePartnerId = table.Column(type: "bigint", nullable: false, comment: "推广人标识。"), - OrderId = table.Column(type: "bigint", nullable: false, comment: "关联订单。"), - BuyerUserId = table.Column(type: "bigint", nullable: false, comment: "用户 ID。"), - OrderAmount = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false, comment: "订单金额。"), - EstimatedCommission = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false, comment: "预计佣金。"), - Status = table.Column(type: "integer", nullable: false, comment: "当前状态。"), - SettledAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "结算完成时间。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_affiliate_orders", x => x.Id); - }, - comment: "分销订单记录。"); - - migrationBuilder.CreateTable( - name: "affiliate_partners", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - UserId = table.Column(type: "bigint", nullable: true, comment: "用户 ID(如绑定平台账号)。"), - DisplayName = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "昵称或渠道名称。"), - Phone = table.Column(type: "character varying(32)", maxLength: 32, nullable: true, comment: "联系电话。"), - ChannelType = table.Column(type: "integer", nullable: false, comment: "渠道类型。"), - CommissionRate = table.Column(type: "numeric", nullable: false, comment: "分成比例(0-1)。"), - Status = table.Column(type: "integer", nullable: false, comment: "当前状态。"), - Remarks = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "审核备注。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_affiliate_partners", x => x.Id); - }, - comment: "分销/推广合作伙伴。"); - - migrationBuilder.CreateTable( - name: "affiliate_payouts", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - AffiliatePartnerId = table.Column(type: "bigint", nullable: false, comment: "合作伙伴标识。"), - Period = table.Column(type: "character varying(32)", maxLength: 32, nullable: false, comment: "结算周期描述。"), - Amount = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false, comment: "结算金额。"), - Status = table.Column(type: "integer", nullable: false, comment: "状态。"), - PaidAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "打款时间。"), - Remarks = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "备注。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_affiliate_payouts", x => x.Id); - }, - comment: "佣金结算记录。"); - - migrationBuilder.CreateTable( - name: "cart_item_addons", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - CartItemId = table.Column(type: "bigint", nullable: false, comment: "所属购物车条目。"), - Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "选项名称。"), - ExtraPrice = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false, comment: "附加价格。"), - OptionId = table.Column(type: "bigint", nullable: true, comment: "选项 ID(可对应 ProductAddonOption)。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_cart_item_addons", x => x.Id); - }, - comment: "购物车条目的加料/附加项。"); - - migrationBuilder.CreateTable( - name: "cart_items", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - ShoppingCartId = table.Column(type: "bigint", nullable: false, comment: "所属购物车标识。"), - ProductId = table.Column(type: "bigint", nullable: false, comment: "商品或 SKU 标识。"), - ProductSkuId = table.Column(type: "bigint", nullable: true, comment: "SKU 标识。"), - ProductName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, comment: "商品名称快照。"), - UnitPrice = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false, comment: "单价快照。"), - Quantity = table.Column(type: "integer", nullable: false, comment: "数量。"), - Remark = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "自定义备注(口味要求)。"), - Status = table.Column(type: "integer", nullable: false, comment: "状态。"), - AttributesJson = table.Column(type: "text", nullable: true, comment: "扩展 JSON(规格、加料选项等)。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_cart_items", x => x.Id); - }, - comment: "购物车条目。"); - - migrationBuilder.CreateTable( - name: "chat_messages", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - ChatSessionId = table.Column(type: "bigint", nullable: false, comment: "会话标识。"), - SenderType = table.Column(type: "integer", nullable: false, comment: "发送方类型。"), - SenderUserId = table.Column(type: "bigint", nullable: true, comment: "发送方用户 ID。"), - Content = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: false, comment: "消息内容。"), - ContentType = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "消息类型(文字/图片/语音等)。"), - IsRead = table.Column(type: "boolean", nullable: false, comment: "是否已读。"), - ReadAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "读取时间。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_chat_messages", x => x.Id); - }, - comment: "会话消息。"); - - migrationBuilder.CreateTable( - name: "chat_sessions", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - SessionCode = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "会话编号。"), - CustomerUserId = table.Column(type: "bigint", nullable: false, comment: "顾客用户 ID。"), - AgentUserId = table.Column(type: "bigint", nullable: true, comment: "当前客服员工 ID。"), - StoreId = table.Column(type: "bigint", nullable: true, comment: "所属门店(可空为平台)。"), - Status = table.Column(type: "integer", nullable: false, comment: "会话状态。"), - IsBotActive = table.Column(type: "boolean", nullable: false, comment: "是否机器人接待中。"), - StartedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "开始时间。"), - EndedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "结束时间。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_chat_sessions", x => x.Id); - }, - comment: "客服会话。"); - - migrationBuilder.CreateTable( - name: "checkin_campaigns", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, comment: "活动名称。"), - Description = table.Column(type: "character varying(512)", maxLength: 512, nullable: true, comment: "活动描述。"), - StartDate = table.Column(type: "timestamp with time zone", nullable: false, comment: "开始日期。"), - EndDate = table.Column(type: "timestamp with time zone", nullable: false, comment: "结束日期。"), - AllowMakeupCount = table.Column(type: "integer", nullable: false, comment: "支持补签次数。"), - RewardsJson = table.Column(type: "text", nullable: false, comment: "连签奖励 JSON。"), - Status = table.Column(type: "integer", nullable: false, comment: "状态。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_checkin_campaigns", x => x.Id); - }, - comment: "签到活动配置。"); - - migrationBuilder.CreateTable( - name: "checkin_records", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - CheckInCampaignId = table.Column(type: "bigint", nullable: false, comment: "活动标识。"), - UserId = table.Column(type: "bigint", nullable: false, comment: "用户标识。"), - CheckInDate = table.Column(type: "timestamp with time zone", nullable: false, comment: "签到日期(本地)。"), - IsMakeup = table.Column(type: "boolean", nullable: false, comment: "是否补签。"), - RewardJson = table.Column(type: "text", nullable: false, comment: "获得奖励 JSON。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_checkin_records", x => x.Id); - }, - comment: "用户签到记录。"); - - migrationBuilder.CreateTable( - name: "checkout_sessions", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - UserId = table.Column(type: "bigint", nullable: false, comment: "用户标识。"), - StoreId = table.Column(type: "bigint", nullable: false, comment: "门店标识。"), - SessionToken = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "会话 Token。"), - Status = table.Column(type: "integer", nullable: false, comment: "会话状态。"), - ValidationResultJson = table.Column(type: "text", nullable: false, comment: "校验结果明细 JSON。"), - ExpiresAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "过期时间(UTC)。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_checkout_sessions", x => x.Id); - }, - comment: "结账会话,记录校验上下文。"); - - migrationBuilder.CreateTable( - name: "community_comments", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - PostId = table.Column(type: "bigint", nullable: false, comment: "动态标识。"), - AuthorUserId = table.Column(type: "bigint", nullable: false, comment: "评论人。"), - Content = table.Column(type: "character varying(512)", maxLength: 512, nullable: false, comment: "评论内容。"), - ParentId = table.Column(type: "bigint", nullable: true, comment: "父级评论 ID。"), - IsDeleted = table.Column(type: "boolean", nullable: false, comment: "状态。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_community_comments", x => x.Id); - }, - comment: "社区评论。"); - - migrationBuilder.CreateTable( - name: "community_posts", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - AuthorUserId = table.Column(type: "bigint", nullable: false, comment: "作者用户 ID。"), - Title = table.Column(type: "character varying(128)", maxLength: 128, nullable: true, comment: "标题。"), - Content = table.Column(type: "text", nullable: false, comment: "内容。"), - MediaJson = table.Column(type: "text", nullable: true, comment: "媒体资源 JSON。"), - Status = table.Column(type: "integer", nullable: false, comment: "状态。"), - LikeCount = table.Column(type: "integer", nullable: false, comment: "点赞数。"), - CommentCount = table.Column(type: "integer", nullable: false, comment: "评论数。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_community_posts", x => x.Id); - }, - comment: "社区动态。"); - - migrationBuilder.CreateTable( - name: "community_reactions", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - PostId = table.Column(type: "bigint", nullable: false, comment: "动态 ID。"), - UserId = table.Column(type: "bigint", nullable: false, comment: "用户 ID。"), - ReactionType = table.Column(type: "integer", nullable: false, comment: "反应类型。"), - ReactedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "时间戳。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_community_reactions", x => x.Id); - }, - comment: "社区互动反馈。"); - - migrationBuilder.CreateTable( - name: "coupon_templates", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, comment: "模板名称。"), - CouponType = table.Column(type: "integer", nullable: false, comment: "券类型。"), - Value = table.Column(type: "numeric", nullable: false, comment: "面值或折扣额度。"), - DiscountCap = table.Column(type: "numeric", nullable: true, comment: "折扣上限(针对折扣券)。"), - MinimumSpend = table.Column(type: "numeric", nullable: true, comment: "最低消费门槛。"), - ValidFrom = table.Column(type: "timestamp with time zone", nullable: true, comment: "可用开始时间。"), - ValidTo = table.Column(type: "timestamp with time zone", nullable: true, comment: "可用结束时间。"), - RelativeValidDays = table.Column(type: "integer", nullable: true, comment: "有效天数(相对发放时间)。"), - TotalQuantity = table.Column(type: "integer", nullable: true, comment: "总发放数量上限。"), - ClaimedQuantity = table.Column(type: "integer", nullable: false, comment: "已领取数量。"), - StoreScopeJson = table.Column(type: "text", nullable: true, comment: "适用门店 ID 集合(JSON)。"), - ProductScopeJson = table.Column(type: "text", nullable: true, comment: "适用品类或商品范围(JSON)。"), - ChannelsJson = table.Column(type: "text", nullable: true, comment: "发放渠道(JSON)。"), - AllowStack = table.Column(type: "boolean", nullable: false, comment: "是否允许叠加其他优惠。"), - Status = table.Column(type: "integer", nullable: false, comment: "状态。"), - Description = table.Column(type: "character varying(512)", maxLength: 512, nullable: true, comment: "备注。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_coupon_templates", x => x.Id); - }, - comment: "优惠券模板。"); - - migrationBuilder.CreateTable( - name: "coupons", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - CouponTemplateId = table.Column(type: "bigint", nullable: false, comment: "模板标识。"), - Code = table.Column(type: "character varying(32)", maxLength: 32, nullable: false, comment: "券码或序列号。"), - UserId = table.Column(type: "bigint", nullable: false, comment: "归属用户。"), - OrderId = table.Column(type: "bigint", nullable: true, comment: "订单 ID(已使用时记录)。"), - Status = table.Column(type: "integer", nullable: false, comment: "状态。"), - IssuedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "发放时间。"), - UsedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "使用时间。"), - ExpireAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "到期时间。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_coupons", x => x.Id); - }, - comment: "用户领取的券。"); - - migrationBuilder.CreateTable( - name: "delivery_events", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - DeliveryOrderId = table.Column(type: "bigint", nullable: false, comment: "配送单标识。"), - EventType = table.Column(type: "integer", nullable: false, comment: "事件类型。"), - Message = table.Column(type: "character varying(256)", maxLength: 256, nullable: false, comment: "事件描述。"), - Payload = table.Column(type: "text", nullable: true, comment: "原始数据 JSON。"), - OccurredAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "发生时间。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_delivery_events", x => x.Id); - }, - comment: "配送状态事件流水。"); - - migrationBuilder.CreateTable( - name: "delivery_orders", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - OrderId = table.Column(type: "bigint", nullable: false), - Provider = table.Column(type: "integer", nullable: false, comment: "配送服务商。"), - ProviderOrderId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "第三方配送单号。"), - Status = table.Column(type: "integer", nullable: false, comment: "状态。"), - DeliveryFee = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: true, comment: "配送费。"), - CourierName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "骑手姓名。"), - CourierPhone = table.Column(type: "character varying(32)", maxLength: 32, nullable: true, comment: "骑手电话。"), - DispatchedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "下发时间。"), - PickedUpAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "取餐时间。"), - DeliveredAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "完成时间。"), - FailureReason = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "异常原因。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_delivery_orders", x => x.Id); - }, - comment: "配送单。"); - - migrationBuilder.CreateTable( - name: "group_orders", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - StoreId = table.Column(type: "bigint", nullable: false, comment: "门店标识。"), - ProductId = table.Column(type: "bigint", nullable: false, comment: "关联商品或套餐。"), - GroupOrderNo = table.Column(type: "character varying(32)", maxLength: 32, nullable: false, comment: "拼单编号。"), - LeaderUserId = table.Column(type: "bigint", nullable: false, comment: "团长用户 ID。"), - TargetCount = table.Column(type: "integer", nullable: false, comment: "成团需要的人数。"), - CurrentCount = table.Column(type: "integer", nullable: false, comment: "当前已参与人数。"), - GroupPrice = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false, comment: "拼团价格。"), - StartAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "开始时间。"), - EndAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "结束时间。"), - Status = table.Column(type: "integer", nullable: false, comment: "拼团状态。"), - SucceededAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "成团时间。"), - CancelledAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "取消时间。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_group_orders", x => x.Id); - }, - comment: "拼单活动。"); - - migrationBuilder.CreateTable( - name: "group_participants", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - GroupOrderId = table.Column(type: "bigint", nullable: false, comment: "拼单活动标识。"), - OrderId = table.Column(type: "bigint", nullable: false, comment: "对应订单标识。"), - UserId = table.Column(type: "bigint", nullable: false, comment: "用户标识。"), - Status = table.Column(type: "integer", nullable: false, comment: "参与状态。"), - JoinedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "参与时间。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_group_participants", x => x.Id); - }, - comment: "拼单参与者。"); - - migrationBuilder.CreateTable( - name: "inventory_adjustments", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - InventoryItemId = table.Column(type: "bigint", nullable: false, comment: "对应的库存记录标识。"), - AdjustmentType = table.Column(type: "integer", nullable: false, comment: "调整类型。"), - Quantity = table.Column(type: "integer", nullable: false, comment: "调整数量,正数增加,负数减少。"), - Reason = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "原因说明。"), - OperatorId = table.Column(type: "bigint", nullable: true, comment: "操作人标识。"), - OccurredAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "发生时间。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_inventory_adjustments", x => x.Id); - }, - comment: "库存调整记录。"); - - migrationBuilder.CreateTable( - name: "inventory_batches", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - StoreId = table.Column(type: "bigint", nullable: false, comment: "门店标识。"), - ProductSkuId = table.Column(type: "bigint", nullable: false, comment: "SKU 标识。"), - BatchNumber = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "批次编号。"), - ProductionDate = table.Column(type: "timestamp with time zone", nullable: true, comment: "生产日期。"), - ExpireDate = table.Column(type: "timestamp with time zone", nullable: true, comment: "过期日期。"), - Quantity = table.Column(type: "integer", nullable: false, comment: "入库数量。"), - RemainingQuantity = table.Column(type: "integer", nullable: false, comment: "剩余数量。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_inventory_batches", x => x.Id); - }, - comment: "SKU 批次信息。"); - - migrationBuilder.CreateTable( - name: "inventory_items", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - StoreId = table.Column(type: "bigint", nullable: false, comment: "门店标识。"), - ProductSkuId = table.Column(type: "bigint", nullable: false, comment: "SKU 标识。"), - BatchNumber = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "批次编号,可为空表示混批。"), - QuantityOnHand = table.Column(type: "integer", nullable: false, comment: "可用库存。"), - QuantityReserved = table.Column(type: "integer", nullable: false, comment: "已锁定库存(订单占用)。"), - SafetyStock = table.Column(type: "integer", nullable: true, comment: "安全库存阈值。"), - Location = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "储位或仓位信息。"), - ExpireDate = table.Column(type: "timestamp with time zone", nullable: true, comment: "过期日期。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_inventory_items", x => x.Id); - }, - comment: "SKU 在门店的库存信息。"); - - migrationBuilder.CreateTable( - name: "map_locations", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - StoreId = table.Column(type: "bigint", nullable: true, comment: "关联门店 ID,可空表示独立 POI。"), - Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, comment: "名称。"), - Address = table.Column(type: "character varying(256)", maxLength: 256, nullable: false, comment: "地址。"), - Longitude = table.Column(type: "double precision", nullable: false, comment: "经度。"), - Latitude = table.Column(type: "double precision", nullable: false, comment: "纬度。"), - Landmark = table.Column(type: "character varying(128)", maxLength: 128, nullable: true, comment: "打车/导航落点描述。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_map_locations", x => x.Id); - }, - comment: "地图 POI 信息,用于门店定位和推荐。"); - - migrationBuilder.CreateTable( - name: "member_growth_logs", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - MemberId = table.Column(type: "bigint", nullable: false, comment: "会员标识。"), - ChangeValue = table.Column(type: "integer", nullable: false, comment: "变动数量。"), - CurrentValue = table.Column(type: "integer", nullable: false, comment: "当前成长值。"), - Notes = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "备注。"), - OccurredAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "发生时间。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_member_growth_logs", x => x.Id); - }, - comment: "成长值变动日志。"); - - migrationBuilder.CreateTable( - name: "member_point_ledgers", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - MemberId = table.Column(type: "bigint", nullable: false, comment: "会员标识。"), - ChangeAmount = table.Column(type: "integer", nullable: false, comment: "变动数量,可为负值。"), - BalanceAfterChange = table.Column(type: "integer", nullable: false, comment: "变动后余额。"), - Reason = table.Column(type: "integer", nullable: false, comment: "变动原因。"), - SourceId = table.Column(type: "bigint", nullable: true, comment: "来源 ID(订单、活动等)。"), - OccurredAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "发生时间。"), - ExpireAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "过期时间(如适用)。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_member_point_ledgers", x => x.Id); - }, - comment: "积分变动流水。"); - - migrationBuilder.CreateTable( - name: "member_profiles", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - UserId = table.Column(type: "bigint", nullable: false, comment: "用户标识。"), - Mobile = table.Column(type: "character varying(32)", maxLength: 32, nullable: false, comment: "手机号。"), - Nickname = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "昵称。"), - AvatarUrl = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "头像。"), - MemberTierId = table.Column(type: "bigint", nullable: true, comment: "当前会员等级 ID。"), - Status = table.Column(type: "integer", nullable: false, comment: "会员状态。"), - PointsBalance = table.Column(type: "integer", nullable: false, comment: "会员积分余额。"), - GrowthValue = table.Column(type: "integer", nullable: false, comment: "成长值/经验值。"), - BirthDate = table.Column(type: "timestamp with time zone", nullable: true, comment: "生日。"), - JoinedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "注册时间。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_member_profiles", x => x.Id); - }, - comment: "会员档案。"); - - migrationBuilder.CreateTable( - name: "member_tiers", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "等级名称。"), - RequiredGrowth = table.Column(type: "integer", nullable: false, comment: "所需成长值。"), - BenefitsJson = table.Column(type: "text", nullable: false, comment: "等级权益(JSON)。"), - SortOrder = table.Column(type: "integer", nullable: false, comment: "排序值。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_member_tiers", x => x.Id); - }, - comment: "会员等级定义。"); - - migrationBuilder.CreateTable( - name: "merchant_contracts", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - MerchantId = table.Column(type: "bigint", nullable: false, comment: "所属商户标识。"), - ContractNumber = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "合同编号。"), - Status = table.Column(type: "integer", nullable: false, comment: "合同状态。"), - StartDate = table.Column(type: "timestamp with time zone", nullable: false, comment: "合同开始时间。"), - EndDate = table.Column(type: "timestamp with time zone", nullable: false, comment: "合同结束时间。"), - FileUrl = table.Column(type: "character varying(512)", maxLength: 512, nullable: false, comment: "合同文件存储地址。"), - SignedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "签署时间。"), - TerminatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "终止时间。"), - TerminationReason = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "终止原因。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_merchant_contracts", x => x.Id); - }, - comment: "商户合同记录。"); - - migrationBuilder.CreateTable( - name: "merchant_documents", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - MerchantId = table.Column(type: "bigint", nullable: false, comment: "所属商户标识。"), - DocumentType = table.Column(type: "integer", nullable: false, comment: "证照类型。"), - Status = table.Column(type: "integer", nullable: false, comment: "审核状态。"), - FileUrl = table.Column(type: "character varying(512)", maxLength: 512, nullable: false, comment: "证照文件链接。"), - DocumentNumber = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "证照编号。"), - IssuedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "签发日期。"), - ExpiresAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "到期日期。"), - Remarks = table.Column(type: "text", nullable: true, comment: "审核备注或驳回原因。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_merchant_documents", x => x.Id); - }, - comment: "商户提交的资质或证照材料。"); - - migrationBuilder.CreateTable( - name: "merchant_staff", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - MerchantId = table.Column(type: "bigint", nullable: false, comment: "所属商户标识。"), - StoreId = table.Column(type: "bigint", nullable: true, comment: "可选的关联门店 ID。"), - Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "员工姓名。"), - Phone = table.Column(type: "character varying(32)", maxLength: 32, nullable: false, comment: "手机号。"), - Email = table.Column(type: "character varying(128)", maxLength: 128, nullable: true, comment: "邮箱地址。"), - IdentityUserId = table.Column(type: "bigint", nullable: true, comment: "登录账号 ID(指向统一身份体系)。"), - RoleType = table.Column(type: "integer", nullable: false, comment: "员工角色类型。"), - Status = table.Column(type: "integer", nullable: false, comment: "员工状态。"), - PermissionsJson = table.Column(type: "text", nullable: true, comment: "自定义权限(JSON)。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_merchant_staff", x => x.Id); - }, - comment: "商户员工账号,支持门店维度分配。"); - - migrationBuilder.CreateTable( - name: "merchants", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - BrandName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, comment: "品牌名称(对外展示)。"), - BrandAlias = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "品牌简称或别名。"), - LogoUrl = table.Column(type: "text", nullable: true, comment: "品牌 Logo。"), - Category = table.Column(type: "text", nullable: true, comment: "品牌所属品类,如火锅、咖啡等。"), - BusinessLicenseNumber = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "营业执照号。"), - BusinessLicenseImageUrl = table.Column(type: "text", nullable: true, comment: "营业执照扫描件地址。"), - TaxNumber = table.Column(type: "text", nullable: true, comment: "税号/统一社会信用代码。"), - LegalPerson = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "法人或负责人姓名。"), - ContactPhone = table.Column(type: "character varying(32)", maxLength: 32, nullable: false, comment: "联系电话。"), - ContactEmail = table.Column(type: "character varying(128)", maxLength: 128, nullable: true, comment: "联系邮箱。"), - ServicePhone = table.Column(type: "text", nullable: true, comment: "客服电话。"), - SupportEmail = table.Column(type: "text", nullable: true, comment: "客服邮箱。"), - Province = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "所在省份。"), - City = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "所在城市。"), - District = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "所在区县。"), - Address = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "详细地址。"), - Longitude = table.Column(type: "double precision", nullable: true, comment: "经度信息。"), - Latitude = table.Column(type: "double precision", nullable: true, comment: "纬度信息。"), - Status = table.Column(type: "integer", nullable: false, comment: "入驻状态。"), - ReviewRemarks = table.Column(type: "character varying(512)", maxLength: 512, nullable: true, comment: "审核备注或驳回原因。"), - JoinedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "入驻时间。"), - LastReviewedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次审核时间。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_merchants", x => x.Id); - }, - comment: "商户主体信息,承载入驻和资质审核结果。"); - - migrationBuilder.CreateTable( - name: "metric_alert_rules", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - MetricDefinitionId = table.Column(type: "bigint", nullable: false, comment: "关联指标。"), - ConditionJson = table.Column(type: "text", nullable: false, comment: "触发条件 JSON。"), - Severity = table.Column(type: "integer", nullable: false, comment: "告警级别。"), - NotificationChannels = table.Column(type: "character varying(256)", maxLength: 256, nullable: false, comment: "通知渠道。"), - Enabled = table.Column(type: "boolean", nullable: false, comment: "是否启用。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_metric_alert_rules", x => x.Id); - }, - comment: "指标告警规则。"); - - migrationBuilder.CreateTable( - name: "metric_definitions", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - Code = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "指标编码。"), - Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, comment: "指标名称。"), - Description = table.Column(type: "character varying(512)", maxLength: 512, nullable: true, comment: "说明。"), - DimensionsJson = table.Column(type: "text", nullable: true, comment: "维度描述 JSON。"), - DefaultAggregation = table.Column(type: "character varying(32)", maxLength: 32, nullable: false, comment: "默认聚合方式。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_metric_definitions", x => x.Id); - }, - comment: "指标定义,描述可观测的数据点。"); - - migrationBuilder.CreateTable( - name: "metric_snapshots", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - MetricDefinitionId = table.Column(type: "bigint", nullable: false, comment: "指标定义 ID。"), - DimensionKey = table.Column(type: "character varying(256)", maxLength: 256, nullable: false, comment: "维度键(JSON)。"), - WindowStart = table.Column(type: "timestamp with time zone", nullable: false, comment: "统计时间窗口开始。"), - WindowEnd = table.Column(type: "timestamp with time zone", nullable: false, comment: "统计时间窗口结束。"), - Value = table.Column(type: "numeric(18,4)", precision: 18, scale: 4, nullable: false, comment: "数值。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_metric_snapshots", x => x.Id); - }, - comment: "指标快照,用于大盘展示。"); - - migrationBuilder.CreateTable( - name: "navigation_requests", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - UserId = table.Column(type: "bigint", nullable: false, comment: "用户 ID。"), - StoreId = table.Column(type: "bigint", nullable: false, comment: "门店 ID。"), - Channel = table.Column(type: "integer", nullable: false, comment: "来源通道(小程序、H5 等)。"), - TargetApp = table.Column(type: "integer", nullable: false, comment: "跳转的地图应用。"), - RequestedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "请求时间。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_navigation_requests", x => x.Id); - }, - comment: "用户发起的导航请求日志。"); - - migrationBuilder.CreateTable( - name: "order_status_histories", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - OrderId = table.Column(type: "bigint", nullable: false, comment: "订单标识。"), - Status = table.Column(type: "integer", nullable: false, comment: "变更后的状态。"), - OperatorId = table.Column(type: "bigint", nullable: true, comment: "操作人标识(可为空表示系统)。"), - Notes = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "备注信息。"), - OccurredAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "发生时间。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_order_status_histories", x => x.Id); - }, - comment: "订单状态流转记录。"); - - migrationBuilder.CreateTable( - name: "orders", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - OrderNo = table.Column(type: "character varying(32)", maxLength: 32, nullable: false, comment: "订单号。"), - StoreId = table.Column(type: "bigint", nullable: false, comment: "门店。"), - Channel = table.Column(type: "integer", nullable: false, comment: "下单渠道。"), - DeliveryType = table.Column(type: "integer", nullable: false, comment: "履约类型。"), - Status = table.Column(type: "integer", nullable: false, comment: "当前状态。"), - PaymentStatus = table.Column(type: "integer", nullable: false, comment: "支付状态。"), - CustomerName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "顾客姓名。"), - CustomerPhone = table.Column(type: "character varying(32)", maxLength: 32, nullable: true, comment: "顾客手机号。"), - TableNo = table.Column(type: "character varying(32)", maxLength: 32, nullable: true, comment: "就餐桌号。"), - QueueNumber = table.Column(type: "character varying(32)", maxLength: 32, nullable: true, comment: "排队号(如有)。"), - ReservationId = table.Column(type: "bigint", nullable: true, comment: "预约 ID。"), - ItemsAmount = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false, comment: "商品总额。"), - DiscountAmount = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false, comment: "优惠金额。"), - PayableAmount = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false, comment: "应付金额。"), - PaidAmount = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false, comment: "实付金额。"), - PaidAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "支付时间。"), - FinishedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "完成时间。"), - CancelledAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "取消时间。"), - CancelReason = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "取消原因。"), - Remark = table.Column(type: "character varying(512)", maxLength: 512, nullable: true, comment: "备注。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_orders", x => x.Id); - }, - comment: "交易订单。"); - - migrationBuilder.CreateTable( - name: "payment_records", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - OrderId = table.Column(type: "bigint", nullable: false, comment: "关联订单。"), - Method = table.Column(type: "integer", nullable: false, comment: "支付方式。"), - Status = table.Column(type: "integer", nullable: false, comment: "支付状态。"), - Amount = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false, comment: "支付金额。"), - TradeNo = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "平台交易号。"), - ChannelTransactionId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "第三方渠道单号。"), - PaidAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "支付完成时间。"), - Remark = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "错误/备注。"), - Payload = table.Column(type: "text", nullable: true, comment: "原始回调内容。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_payment_records", x => x.Id); - }, - comment: "支付流水。"); - - migrationBuilder.CreateTable( - name: "payment_refund_records", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - PaymentRecordId = table.Column(type: "bigint", nullable: false, comment: "原支付记录标识。"), - OrderId = table.Column(type: "bigint", nullable: false, comment: "关联订单标识。"), - Amount = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false, comment: "退款金额。"), - ChannelRefundId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "渠道退款流水号。"), - Status = table.Column(type: "integer", nullable: false, comment: "退款状态。"), - RequestedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "退款请求时间。"), - CompletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "完成时间。"), - Payload = table.Column(type: "text", nullable: true, comment: "渠道返回的原始数据 JSON。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_payment_refund_records", x => x.Id); - }, - comment: "支付渠道退款流水。"); - - migrationBuilder.CreateTable( - name: "product_addon_groups", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - ProductId = table.Column(type: "bigint", nullable: false, comment: "所属商品。"), - Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "分组名称。"), - SelectionType = table.Column(type: "integer", nullable: false, comment: "选择类型。"), - MinSelect = table.Column(type: "integer", nullable: true, comment: "最小选择数量。"), - MaxSelect = table.Column(type: "integer", nullable: true, comment: "最大选择数量。"), - IsRequired = table.Column(type: "boolean", nullable: false, comment: "是否必选。"), - SortOrder = table.Column(type: "integer", nullable: false, comment: "排序值。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_product_addon_groups", x => x.Id); - }, - comment: "加料/做法分组。"); - - migrationBuilder.CreateTable( - name: "product_addon_options", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - AddonGroupId = table.Column(type: "bigint", nullable: false, comment: "所属加料分组。"), - Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "选项名称。"), - ExtraPrice = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: true, comment: "附加价格。"), - IsDefault = table.Column(type: "boolean", nullable: false, comment: "是否默认选项。"), - SortOrder = table.Column(type: "integer", nullable: false, comment: "排序。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_product_addon_options", x => x.Id); - }, - comment: "加料选项。"); - - migrationBuilder.CreateTable( - name: "product_attribute_groups", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - StoreId = table.Column(type: "bigint", nullable: true, comment: "关联门店,可为空表示所有门店共享。"), - ProductId = table.Column(type: "bigint", nullable: false, comment: "所属商品标识。"), - Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "分组名称,例如“辣度”“份量”。"), - SelectionType = table.Column(type: "integer", nullable: false, comment: "选择类型(单选/多选)。"), - IsRequired = table.Column(type: "boolean", nullable: false, comment: "是否必选。"), - SortOrder = table.Column(type: "integer", nullable: false, comment: "显示排序。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_product_attribute_groups", x => x.Id); - }, - comment: "商品规格/属性分组。"); - - migrationBuilder.CreateTable( - name: "product_attribute_options", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - AttributeGroupId = table.Column(type: "bigint", nullable: false, comment: "所属规格组。"), - Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "选项名称。"), - ExtraPrice = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: true, comment: "附加价格。"), - SortOrder = table.Column(type: "integer", nullable: false, comment: "排序。"), - IsDefault = table.Column(type: "boolean", nullable: false, comment: "是否默认选中。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_product_attribute_options", x => x.Id); - }, - comment: "商品规格选项。"); - - migrationBuilder.CreateTable( - name: "product_categories", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - StoreId = table.Column(type: "bigint", nullable: false, comment: "所属门店。"), - Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "分类名称。"), - Description = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "分类描述。"), - SortOrder = table.Column(type: "integer", nullable: false, comment: "排序值。"), - IsEnabled = table.Column(type: "boolean", nullable: false, comment: "是否启用。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_product_categories", x => x.Id); - }, - comment: "商品分类。"); - - migrationBuilder.CreateTable( - name: "product_media_assets", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - ProductId = table.Column(type: "bigint", nullable: false, comment: "商品标识。"), - MediaType = table.Column(type: "integer", nullable: false, comment: "媒体类型。"), - Url = table.Column(type: "character varying(512)", maxLength: 512, nullable: false, comment: "媒资链接。"), - Caption = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "描述或标题。"), - SortOrder = table.Column(type: "integer", nullable: false, comment: "排序。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_product_media_assets", x => x.Id); - }, - comment: "商品媒资素材。"); - - migrationBuilder.CreateTable( - name: "product_pricing_rules", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - ProductId = table.Column(type: "bigint", nullable: false, comment: "所属商品。"), - RuleType = table.Column(type: "integer", nullable: false, comment: "策略类型。"), - ConditionsJson = table.Column(type: "text", nullable: false, comment: "条件描述(JSON),如会员等级、渠道等。"), - Price = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false, comment: "特殊价格。"), - StartTime = table.Column(type: "timestamp with time zone", nullable: true, comment: "生效开始时间。"), - EndTime = table.Column(type: "timestamp with time zone", nullable: true, comment: "生效结束时间。"), - WeekdaysJson = table.Column(type: "text", nullable: true, comment: "生效星期(JSON 数组)。"), - SortOrder = table.Column(type: "integer", nullable: false, comment: "排序值。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_product_pricing_rules", x => x.Id); - }, - comment: "商品价格策略,支持会员价/时段价等。"); - - migrationBuilder.CreateTable( - name: "product_skus", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - ProductId = table.Column(type: "bigint", nullable: false, comment: "所属商品标识。"), - SkuCode = table.Column(type: "character varying(32)", maxLength: 32, nullable: false, comment: "SKU 编码。"), - Barcode = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "条形码。"), - Price = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false, comment: "售价。"), - OriginalPrice = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: true, comment: "原价。"), - StockQuantity = table.Column(type: "integer", nullable: true, comment: "可售库存。"), - Weight = table.Column(type: "numeric(10,3)", precision: 10, scale: 3, nullable: true, comment: "重量(千克)。"), - AttributesJson = table.Column(type: "text", nullable: false, comment: "规格属性 JSON(记录选项 ID)。"), - SortOrder = table.Column(type: "integer", nullable: false, comment: "排序值。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_product_skus", x => x.Id); - }, - comment: "商品 SKU,记录具体规格组合价格。"); - - migrationBuilder.CreateTable( - name: "products", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - StoreId = table.Column(type: "bigint", nullable: false, comment: "所属门店。"), - CategoryId = table.Column(type: "bigint", nullable: false, comment: "所属分类。"), - SpuCode = table.Column(type: "character varying(32)", maxLength: 32, nullable: false, comment: "商品编码。"), - Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, comment: "商品名称。"), - Subtitle = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "副标题/卖点。"), - Unit = table.Column(type: "character varying(16)", maxLength: 16, nullable: true, comment: "售卖单位(份/杯等)。"), - Price = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false, comment: "现价。"), - OriginalPrice = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: true, comment: "原价。"), - StockQuantity = table.Column(type: "integer", nullable: true, comment: "库存数量(可选)。"), - MaxQuantityPerOrder = table.Column(type: "integer", nullable: true, comment: "最大每单限购。"), - Status = table.Column(type: "integer", nullable: false, comment: "商品状态。"), - CoverImage = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "主图。"), - GalleryImages = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true, comment: "Gallery 图片逗号分隔。"), - Description = table.Column(type: "text", nullable: true, comment: "商品描述。"), - EnableDineIn = table.Column(type: "boolean", nullable: false, comment: "支持堂食。"), - EnablePickup = table.Column(type: "boolean", nullable: false, comment: "支持自提。"), - EnableDelivery = table.Column(type: "boolean", nullable: false, comment: "支持配送。"), - IsFeatured = table.Column(type: "boolean", nullable: false, comment: "是否热门推荐。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_products", x => x.Id); - }, - comment: "商品(SPU)信息。"); - - migrationBuilder.CreateTable( - name: "promotion_campaigns", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, comment: "活动名称。"), - PromotionType = table.Column(type: "integer", nullable: false, comment: "活动类型。"), - Status = table.Column(type: "integer", nullable: false, comment: "活动状态。"), - StartAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "开始时间。"), - EndAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "结束时间。"), - Budget = table.Column(type: "numeric", nullable: true, comment: "预算金额。"), - RulesJson = table.Column(type: "text", nullable: false, comment: "活动规则 JSON。"), - AudienceDescription = table.Column(type: "character varying(512)", maxLength: 512, nullable: true, comment: "目标人群描述。"), - BannerUrl = table.Column(type: "character varying(512)", maxLength: 512, nullable: true, comment: "营销素材(如 banner)。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_promotion_campaigns", x => x.Id); - }, - comment: "营销活动配置。"); - - migrationBuilder.CreateTable( - name: "queue_tickets", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - StoreId = table.Column(type: "bigint", nullable: false), - TicketNumber = table.Column(type: "character varying(32)", maxLength: 32, nullable: false, comment: "排队编号。"), - PartySize = table.Column(type: "integer", nullable: false, comment: "就餐人数。"), - Status = table.Column(type: "integer", nullable: false, comment: "状态。"), - EstimatedWaitMinutes = table.Column(type: "integer", nullable: true, comment: "预计等待分钟。"), - CalledAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "叫号时间。"), - ExpiredAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "过号时间。"), - CancelledAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "取消时间。"), - Remark = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "备注。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_queue_tickets", x => x.Id); - }, - comment: "排队叫号。"); - - migrationBuilder.CreateTable( - name: "refund_requests", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - OrderId = table.Column(type: "bigint", nullable: false, comment: "关联订单标识。"), - RefundNo = table.Column(type: "character varying(32)", maxLength: 32, nullable: false, comment: "退款单号。"), - Amount = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false, comment: "申请金额。"), - Reason = table.Column(type: "character varying(256)", maxLength: 256, nullable: false, comment: "申请原因。"), - Status = table.Column(type: "integer", nullable: false, comment: "退款状态。"), - RequestedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "用户提交时间。"), - ProcessedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "审核完成时间。"), - ReviewNotes = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "审核备注。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_refund_requests", x => x.Id); - }, - comment: "售后/退款申请。"); - - migrationBuilder.CreateTable( - name: "reservations", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - StoreId = table.Column(type: "bigint", nullable: false, comment: "门店。"), - ReservationNo = table.Column(type: "character varying(32)", maxLength: 32, nullable: false, comment: "预约号。"), - CustomerName = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "客户姓名。"), - CustomerPhone = table.Column(type: "character varying(32)", maxLength: 32, nullable: false, comment: "联系电话。"), - PeopleCount = table.Column(type: "integer", nullable: false, comment: "用餐人数。"), - ReservationTime = table.Column(type: "timestamp with time zone", nullable: false, comment: "预约时间(UTC)。"), - Status = table.Column(type: "integer", nullable: false, comment: "状态。"), - TablePreference = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "桌型/标签。"), - Remark = table.Column(type: "character varying(512)", maxLength: 512, nullable: true, comment: "备注。"), - CheckInCode = table.Column(type: "character varying(32)", maxLength: 32, nullable: true, comment: "核销码/到店码。"), - CheckedInAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "实际签到时间。"), - CancelledAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "取消时间。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_reservations", x => x.Id); - }, - comment: "预约/预订记录。"); - - migrationBuilder.CreateTable( - name: "shopping_carts", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - UserId = table.Column(type: "bigint", nullable: false, comment: "用户标识。"), - StoreId = table.Column(type: "bigint", nullable: false, comment: "门店标识。"), - Status = table.Column(type: "integer", nullable: false, comment: "购物车状态,包含正常/锁定。"), - TableContext = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "桌码或场景标识(扫码点餐)。"), - DeliveryPreference = table.Column(type: "character varying(32)", maxLength: 32, nullable: true, comment: "履约方式(堂食/自提/配送)缓存。"), - LastModifiedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "最近一次修改时间(UTC)。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_shopping_carts", x => x.Id); - }, - comment: "用户购物车,按租户/门店隔离。"); - - migrationBuilder.CreateTable( - name: "store_business_hours", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - StoreId = table.Column(type: "bigint", nullable: false, comment: "门店标识。"), - DayOfWeek = table.Column(type: "integer", nullable: false, comment: "星期几,0 表示周日。"), - HourType = table.Column(type: "integer", nullable: false, comment: "时段类型(正常营业、休息、预约等)。"), - StartTime = table.Column(type: "interval", nullable: false, comment: "开始时间(本地时间)。"), - EndTime = table.Column(type: "interval", nullable: false, comment: "结束时间(本地时间)。"), - CapacityLimit = table.Column(type: "integer", nullable: true, comment: "最大接待容量或单量限制。"), - Notes = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "备注。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_store_business_hours", x => x.Id); - }, - comment: "门店营业时段配置。"); - - migrationBuilder.CreateTable( - name: "store_delivery_zones", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - StoreId = table.Column(type: "bigint", nullable: false, comment: "门店标识。"), - ZoneName = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "区域名称。"), - PolygonGeoJson = table.Column(type: "text", nullable: false, comment: "GeoJSON 表示的多边形范围。"), - MinimumOrderAmount = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: true, comment: "起送价。"), - DeliveryFee = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: true, comment: "配送费。"), - EstimatedMinutes = table.Column(type: "integer", nullable: true, comment: "预计送达分钟。"), - SortOrder = table.Column(type: "integer", nullable: false, comment: "排序值。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_store_delivery_zones", x => x.Id); - }, - comment: "门店配送范围配置。"); - - migrationBuilder.CreateTable( - name: "store_employee_shifts", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - StoreId = table.Column(type: "bigint", nullable: false, comment: "门店标识。"), - StaffId = table.Column(type: "bigint", nullable: false, comment: "员工标识。"), - ShiftDate = table.Column(type: "timestamp with time zone", nullable: false, comment: "班次日期。"), - StartTime = table.Column(type: "interval", nullable: false, comment: "开始时间。"), - EndTime = table.Column(type: "interval", nullable: false, comment: "结束时间。"), - RoleType = table.Column(type: "integer", nullable: false, comment: "排班角色。"), - Notes = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "备注。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_store_employee_shifts", x => x.Id); - }, - comment: "门店员工排班记录。"); - - migrationBuilder.CreateTable( - name: "store_holidays", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - StoreId = table.Column(type: "bigint", nullable: false, comment: "门店标识。"), - Date = table.Column(type: "timestamp with time zone", nullable: false, comment: "日期。"), - IsClosed = table.Column(type: "boolean", nullable: false, comment: "是否全天闭店。"), - Reason = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "说明内容。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_store_holidays", x => x.Id); - }, - comment: "门店休息日或特殊营业日。"); - - migrationBuilder.CreateTable( - name: "store_table_areas", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - StoreId = table.Column(type: "bigint", nullable: false, comment: "门店标识。"), - Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "区域名称。"), - Description = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "区域描述。"), - SortOrder = table.Column(type: "integer", nullable: false, comment: "排序值。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_store_table_areas", x => x.Id); - }, - comment: "门店桌台区域配置。"); - - migrationBuilder.CreateTable( - name: "store_tables", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - StoreId = table.Column(type: "bigint", nullable: false, comment: "门店标识。"), - AreaId = table.Column(type: "bigint", nullable: true, comment: "所在区域 ID。"), - TableCode = table.Column(type: "character varying(32)", maxLength: 32, nullable: false, comment: "桌码。"), - Capacity = table.Column(type: "integer", nullable: false, comment: "可容纳人数。"), - Tags = table.Column(type: "character varying(128)", maxLength: 128, nullable: true, comment: "桌台标签(堂食、快餐等)。"), - Status = table.Column(type: "integer", nullable: false, comment: "当前桌台状态。"), - QrCodeUrl = table.Column(type: "character varying(512)", maxLength: 512, nullable: true, comment: "桌码二维码地址。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_store_tables", x => x.Id); - }, - comment: "桌台信息与二维码绑定。"); - - migrationBuilder.CreateTable( - name: "stores", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - MerchantId = table.Column(type: "bigint", nullable: false, comment: "所属商户标识。"), - Code = table.Column(type: "character varying(32)", maxLength: 32, nullable: false, comment: "门店编码,便于扫码及外部对接。"), - Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, comment: "门店名称。"), - Phone = table.Column(type: "character varying(32)", maxLength: 32, nullable: true, comment: "联系电话。"), - ManagerName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "门店负责人姓名。"), - Status = table.Column(type: "integer", nullable: false, comment: "门店当前运营状态。"), - Country = table.Column(type: "text", nullable: true, comment: "所在国家或地区。"), - Province = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "所在省份。"), - City = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "所在城市。"), - District = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "区县信息。"), - Address = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "详细地址。"), - Longitude = table.Column(type: "double precision", nullable: true, comment: "高德/腾讯地图经度。"), - Latitude = table.Column(type: "double precision", nullable: true, comment: "纬度。"), - Description = table.Column(type: "text", nullable: true, comment: "门店描述或公告。"), - BusinessHours = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "门店营业时段描述(备用字符串)。"), - SupportsDineIn = table.Column(type: "boolean", nullable: false, comment: "是否支持堂食。"), - SupportsPickup = table.Column(type: "boolean", nullable: false, comment: "是否支持自提。"), - SupportsDelivery = table.Column(type: "boolean", nullable: false, comment: "是否支持配送。"), - SupportsReservation = table.Column(type: "boolean", nullable: false, comment: "支持预约。"), - SupportsQueueing = table.Column(type: "boolean", nullable: false, comment: "支持排队叫号。"), - DeliveryRadiusKm = table.Column(type: "numeric(6,2)", precision: 6, scale: 2, nullable: false, comment: "默认配送半径(公里)。"), - Announcement = table.Column(type: "character varying(512)", maxLength: 512, nullable: true, comment: "门店公告。"), - Tags = table.Column(type: "text", nullable: true, comment: "门店标签(逗号分隔)。"), - CoverImageUrl = table.Column(type: "text", nullable: true, comment: "门店海报。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_stores", x => x.Id); - }, - comment: "门店信息,承载营业配置与能力。"); - - migrationBuilder.CreateTable( - name: "support_tickets", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - TicketNo = table.Column(type: "character varying(32)", maxLength: 32, nullable: false, comment: "工单编号。"), - CustomerUserId = table.Column(type: "bigint", nullable: false, comment: "客户用户 ID。"), - OrderId = table.Column(type: "bigint", nullable: true, comment: "关联订单(如有)。"), - Subject = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, comment: "工单主题。"), - Description = table.Column(type: "text", nullable: false, comment: "工单详情。"), - Priority = table.Column(type: "integer", nullable: false, comment: "优先级。"), - Status = table.Column(type: "integer", nullable: false, comment: "状态。"), - AssignedAgentId = table.Column(type: "bigint", nullable: true, comment: "指派的客服。"), - ClosedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "关闭时间。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_support_tickets", x => x.Id); - }, - comment: "客服工单。"); - - migrationBuilder.CreateTable( - name: "tenant_billing_statements", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - StatementNo = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "账单编号,供对账查询。"), - PeriodStart = table.Column(type: "timestamp with time zone", nullable: false, comment: "账单周期开始时间。"), - PeriodEnd = table.Column(type: "timestamp with time zone", nullable: false, comment: "账单周期结束时间。"), - AmountDue = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false, comment: "应付金额。"), - AmountPaid = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false, comment: "实付金额。"), - Status = table.Column(type: "integer", nullable: false, comment: "当前付款状态。"), - DueDate = table.Column(type: "timestamp with time zone", nullable: false, comment: "到期日。"), - LineItemsJson = table.Column(type: "text", nullable: true, comment: "账单明细 JSON,记录各项费用。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_tenant_billing_statements", x => x.Id); - }, - comment: "租户账单,用于呈现周期性收费。"); - - migrationBuilder.CreateTable( - name: "tenant_notifications", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - Title = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, comment: "通知标题。"), - Message = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: false, comment: "通知正文。"), - Channel = table.Column(type: "integer", nullable: false, comment: "发布通道(站内、邮件、短信等)。"), - Severity = table.Column(type: "integer", nullable: false, comment: "通知重要级别。"), - SentAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "推送时间。"), - ReadAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "租户是否已阅读。"), - MetadataJson = table.Column(type: "text", nullable: true, comment: "附加元数据 JSON。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_tenant_notifications", x => x.Id); - }, - comment: "面向租户的站内通知或消息推送。"); - - migrationBuilder.CreateTable( - name: "tenant_packages", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, comment: "套餐名称,展示给租户的简称。"), - Description = table.Column(type: "character varying(512)", maxLength: 512, nullable: true, comment: "套餐描述,包含适用场景、权益等。"), - PackageType = table.Column(type: "integer", nullable: false, comment: "套餐分类(试用、标准、旗舰等)。"), - MonthlyPrice = table.Column(type: "numeric", nullable: true, comment: "月付价格,单位:人民币元。"), - YearlyPrice = table.Column(type: "numeric", nullable: true, comment: "年付价格,单位:人民币元。"), - MaxStoreCount = table.Column(type: "integer", nullable: true, comment: "允许的最大门店数。"), - MaxAccountCount = table.Column(type: "integer", nullable: true, comment: "允许创建的最大账号数。"), - MaxStorageGb = table.Column(type: "integer", nullable: true, comment: "存储容量上限(GB)。"), - MaxSmsCredits = table.Column(type: "integer", nullable: true, comment: "每月短信额度上限。"), - MaxDeliveryOrders = table.Column(type: "integer", nullable: true, comment: "每月可调用的配送单数量上限。"), - FeaturePoliciesJson = table.Column(type: "text", nullable: true, comment: "权益明细 JSON,记录自定义特性开关。"), - IsActive = table.Column(type: "boolean", nullable: false, comment: "是否仍可售卖。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。") - }, - constraints: table => - { - table.PrimaryKey("PK_tenant_packages", x => x.Id); - }, - comment: "平台提供的租户套餐定义。"); - - migrationBuilder.CreateTable( - name: "tenant_quota_usages", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - QuotaType = table.Column(type: "integer", nullable: false, comment: "配额类型,例如门店数、短信条数等。"), - LimitValue = table.Column(type: "numeric", nullable: false, comment: "当前配额上限。"), - UsedValue = table.Column(type: "numeric", nullable: false, comment: "已消耗的数量。"), - ResetCycle = table.Column(type: "text", nullable: true, comment: "配额刷新周期描述(如月、年)。"), - LastResetAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次重置时间。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_tenant_quota_usages", x => x.Id); - }, - comment: "租户配额使用情况快照。"); - - migrationBuilder.CreateTable( - name: "tenant_subscriptions", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - TenantPackageId = table.Column(type: "bigint", nullable: false, comment: "当前订阅关联的套餐标识。"), - EffectiveFrom = table.Column(type: "timestamp with time zone", nullable: false, comment: "订阅生效时间(UTC)。"), - EffectiveTo = table.Column(type: "timestamp with time zone", nullable: false, comment: "订阅到期时间(UTC)。"), - NextBillingDate = table.Column(type: "timestamp with time zone", nullable: true, comment: "下一个计费时间,配合自动续费使用。"), - Status = table.Column(type: "integer", nullable: false, comment: "订阅当前状态。"), - AutoRenew = table.Column(type: "boolean", nullable: false, comment: "是否开启自动续费。"), - ScheduledPackageId = table.Column(type: "bigint", nullable: true, comment: "若已排期升降配,对应的新套餐 ID。"), - Notes = table.Column(type: "text", nullable: true, comment: "运营备注信息。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_tenant_subscriptions", x => x.Id); - }, - comment: "租户套餐订阅记录。"); - - migrationBuilder.CreateTable( - name: "tenants", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - Code = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "租户短编码,作为跨系统引用的唯一标识。"), - Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, comment: "租户全称或品牌名称。"), - ShortName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "对外展示的简称。"), - LegalEntityName = table.Column(type: "text", nullable: true, comment: "法人或公司主体名称。"), - Industry = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "所属行业,如餐饮、零售等。"), - LogoUrl = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "LOGO 图片地址。"), - CoverImageUrl = table.Column(type: "text", nullable: true, comment: "品牌海报或封面图。"), - Website = table.Column(type: "text", nullable: true, comment: "官网或主要宣传链接。"), - Country = table.Column(type: "text", nullable: true, comment: "所在国家/地区。"), - Province = table.Column(type: "text", nullable: true, comment: "所在省份或州。"), - City = table.Column(type: "text", nullable: true, comment: "所在城市。"), - Address = table.Column(type: "text", nullable: true, comment: "详细地址信息。"), - ContactName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "主联系人姓名。"), - ContactPhone = table.Column(type: "character varying(32)", maxLength: 32, nullable: true, comment: "主联系人电话。"), - ContactEmail = table.Column(type: "character varying(128)", maxLength: 128, nullable: true, comment: "主联系人邮箱。"), - PrimaryOwnerUserId = table.Column(type: "bigint", nullable: true, comment: "系统内对应的租户所有者账号 ID。"), - Status = table.Column(type: "integer", nullable: false, comment: "租户当前状态,涵盖审核、启用、停用等场景。"), - EffectiveFrom = table.Column(type: "timestamp with time zone", nullable: true, comment: "服务生效时间(UTC)。"), - EffectiveTo = table.Column(type: "timestamp with time zone", nullable: true, comment: "服务到期时间(UTC)。"), - SuspendedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次暂停服务时间。"), - SuspensionReason = table.Column(type: "text", nullable: true, comment: "暂停或终止的原因说明。"), - Tags = table.Column(type: "text", nullable: true, comment: "业务标签集合(逗号分隔)。"), - Remarks = table.Column(type: "character varying(512)", maxLength: 512, nullable: true, comment: "备注信息,用于运营记录特殊说明。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。") - }, - constraints: table => - { - table.PrimaryKey("PK_tenants", x => x.Id); - }, - comment: "平台租户信息,描述租户的生命周期与基础资料。"); - - migrationBuilder.CreateTable( - name: "ticket_comments", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - SupportTicketId = table.Column(type: "bigint", nullable: false, comment: "工单标识。"), - AuthorUserId = table.Column(type: "bigint", nullable: true, comment: "评论人 ID。"), - Content = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: false, comment: "评论内容。"), - IsInternal = table.Column(type: "boolean", nullable: false, comment: "是否内部备注。"), - AttachmentsJson = table.Column(type: "text", nullable: true, comment: "附件 JSON。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_ticket_comments", x => x.Id); - }, - comment: "工单评论/流转记录。"); - - migrationBuilder.CreateTable( - name: "order_items", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - OrderId = table.Column(type: "bigint", nullable: false, comment: "订单 ID。"), - ProductId = table.Column(type: "bigint", nullable: false, comment: "商品 ID。"), - ProductName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, comment: "商品名称。"), - SkuName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true, comment: "SKU/规格描述。"), - Unit = table.Column(type: "character varying(16)", maxLength: 16, nullable: true, comment: "单位。"), - Quantity = table.Column(type: "integer", nullable: false, comment: "数量。"), - UnitPrice = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false, comment: "单价。"), - DiscountAmount = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false, comment: "折扣金额。"), - SubTotal = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false, comment: "小计。"), - AttributesJson = table.Column(type: "text", nullable: true, comment: "自定义属性 JSON。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_order_items", x => x.Id); - table.ForeignKey( - name: "FK_order_items_orders_OrderId", - column: x => x.OrderId, - principalTable: "orders", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }, - comment: "订单明细。"); - - migrationBuilder.CreateIndex( - name: "IX_affiliate_orders_TenantId_AffiliatePartnerId_OrderId", - table: "affiliate_orders", - columns: new[] { "TenantId", "AffiliatePartnerId", "OrderId" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_affiliate_partners_TenantId_DisplayName", - table: "affiliate_partners", - columns: new[] { "TenantId", "DisplayName" }); - - migrationBuilder.CreateIndex( - name: "IX_affiliate_payouts_TenantId_AffiliatePartnerId_Period", - table: "affiliate_payouts", - columns: new[] { "TenantId", "AffiliatePartnerId", "Period" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_cart_items_TenantId_ShoppingCartId", - table: "cart_items", - columns: new[] { "TenantId", "ShoppingCartId" }); - - migrationBuilder.CreateIndex( - name: "IX_chat_messages_TenantId_ChatSessionId_CreatedAt", - table: "chat_messages", - columns: new[] { "TenantId", "ChatSessionId", "CreatedAt" }); - - migrationBuilder.CreateIndex( - name: "IX_chat_sessions_TenantId_SessionCode", - table: "chat_sessions", - columns: new[] { "TenantId", "SessionCode" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_checkin_campaigns_TenantId_Name", - table: "checkin_campaigns", - columns: new[] { "TenantId", "Name" }); - - migrationBuilder.CreateIndex( - name: "IX_checkin_records_TenantId_CheckInCampaignId_UserId_CheckInDa~", - table: "checkin_records", - columns: new[] { "TenantId", "CheckInCampaignId", "UserId", "CheckInDate" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_checkout_sessions_TenantId_SessionToken", - table: "checkout_sessions", - columns: new[] { "TenantId", "SessionToken" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_community_comments_TenantId_PostId_CreatedAt", - table: "community_comments", - columns: new[] { "TenantId", "PostId", "CreatedAt" }); - - migrationBuilder.CreateIndex( - name: "IX_community_posts_TenantId_AuthorUserId_CreatedAt", - table: "community_posts", - columns: new[] { "TenantId", "AuthorUserId", "CreatedAt" }); - - migrationBuilder.CreateIndex( - name: "IX_community_reactions_TenantId_PostId_UserId", - table: "community_reactions", - columns: new[] { "TenantId", "PostId", "UserId" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_coupons_TenantId_Code", - table: "coupons", - columns: new[] { "TenantId", "Code" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_delivery_events_TenantId_DeliveryOrderId_EventType", - table: "delivery_events", - columns: new[] { "TenantId", "DeliveryOrderId", "EventType" }); - - migrationBuilder.CreateIndex( - name: "IX_delivery_orders_TenantId_OrderId", - table: "delivery_orders", - columns: new[] { "TenantId", "OrderId" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_group_orders_TenantId_GroupOrderNo", - table: "group_orders", - columns: new[] { "TenantId", "GroupOrderNo" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_group_participants_TenantId_GroupOrderId_UserId", - table: "group_participants", - columns: new[] { "TenantId", "GroupOrderId", "UserId" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_inventory_adjustments_TenantId_InventoryItemId_OccurredAt", - table: "inventory_adjustments", - columns: new[] { "TenantId", "InventoryItemId", "OccurredAt" }); - - migrationBuilder.CreateIndex( - name: "IX_inventory_batches_TenantId_StoreId_ProductSkuId_BatchNumber", - table: "inventory_batches", - columns: new[] { "TenantId", "StoreId", "ProductSkuId", "BatchNumber" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_inventory_items_TenantId_StoreId_ProductSkuId_BatchNumber", - table: "inventory_items", - columns: new[] { "TenantId", "StoreId", "ProductSkuId", "BatchNumber" }); - - migrationBuilder.CreateIndex( - name: "IX_map_locations_TenantId_StoreId", - table: "map_locations", - columns: new[] { "TenantId", "StoreId" }); - - migrationBuilder.CreateIndex( - name: "IX_member_growth_logs_TenantId_MemberId_OccurredAt", - table: "member_growth_logs", - columns: new[] { "TenantId", "MemberId", "OccurredAt" }); - - migrationBuilder.CreateIndex( - name: "IX_member_point_ledgers_TenantId_MemberId_OccurredAt", - table: "member_point_ledgers", - columns: new[] { "TenantId", "MemberId", "OccurredAt" }); - - migrationBuilder.CreateIndex( - name: "IX_member_profiles_TenantId_Mobile", - table: "member_profiles", - columns: new[] { "TenantId", "Mobile" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_member_tiers_TenantId_Name", - table: "member_tiers", - columns: new[] { "TenantId", "Name" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_merchant_contracts_TenantId_MerchantId_ContractNumber", - table: "merchant_contracts", - columns: new[] { "TenantId", "MerchantId", "ContractNumber" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_merchant_documents_TenantId_MerchantId_DocumentType", - table: "merchant_documents", - columns: new[] { "TenantId", "MerchantId", "DocumentType" }); - - migrationBuilder.CreateIndex( - name: "IX_merchant_staff_TenantId_MerchantId_Phone", - table: "merchant_staff", - columns: new[] { "TenantId", "MerchantId", "Phone" }); - - migrationBuilder.CreateIndex( - name: "IX_merchants_TenantId", - table: "merchants", - column: "TenantId"); - - migrationBuilder.CreateIndex( - name: "IX_metric_alert_rules_TenantId_MetricDefinitionId_Severity", - table: "metric_alert_rules", - columns: new[] { "TenantId", "MetricDefinitionId", "Severity" }); - - migrationBuilder.CreateIndex( - name: "IX_metric_definitions_TenantId_Code", - table: "metric_definitions", - columns: new[] { "TenantId", "Code" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_metric_snapshots_TenantId_MetricDefinitionId_DimensionKey_W~", - table: "metric_snapshots", - columns: new[] { "TenantId", "MetricDefinitionId", "DimensionKey", "WindowStart", "WindowEnd" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_navigation_requests_TenantId_UserId_StoreId_RequestedAt", - table: "navigation_requests", - columns: new[] { "TenantId", "UserId", "StoreId", "RequestedAt" }); - - migrationBuilder.CreateIndex( - name: "IX_order_items_OrderId", - table: "order_items", - column: "OrderId"); - - migrationBuilder.CreateIndex( - name: "IX_order_items_TenantId_OrderId", - table: "order_items", - columns: new[] { "TenantId", "OrderId" }); - - migrationBuilder.CreateIndex( - name: "IX_order_status_histories_TenantId_OrderId_OccurredAt", - table: "order_status_histories", - columns: new[] { "TenantId", "OrderId", "OccurredAt" }); - - migrationBuilder.CreateIndex( - name: "IX_orders_TenantId_OrderNo", - table: "orders", - columns: new[] { "TenantId", "OrderNo" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_orders_TenantId_StoreId_Status", - table: "orders", - columns: new[] { "TenantId", "StoreId", "Status" }); - - migrationBuilder.CreateIndex( - name: "IX_payment_records_TenantId_OrderId", - table: "payment_records", - columns: new[] { "TenantId", "OrderId" }); - - migrationBuilder.CreateIndex( - name: "IX_payment_refund_records_TenantId_PaymentRecordId", - table: "payment_refund_records", - columns: new[] { "TenantId", "PaymentRecordId" }); - - migrationBuilder.CreateIndex( - name: "IX_product_addon_groups_TenantId_ProductId_Name", - table: "product_addon_groups", - columns: new[] { "TenantId", "ProductId", "Name" }); - - migrationBuilder.CreateIndex( - name: "IX_product_attribute_groups_TenantId_StoreId_Name", - table: "product_attribute_groups", - columns: new[] { "TenantId", "StoreId", "Name" }); - - migrationBuilder.CreateIndex( - name: "IX_product_attribute_options_TenantId_AttributeGroupId_Name", - table: "product_attribute_options", - columns: new[] { "TenantId", "AttributeGroupId", "Name" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_product_categories_TenantId_StoreId", - table: "product_categories", - columns: new[] { "TenantId", "StoreId" }); - - migrationBuilder.CreateIndex( - name: "IX_product_pricing_rules_TenantId_ProductId_RuleType", - table: "product_pricing_rules", - columns: new[] { "TenantId", "ProductId", "RuleType" }); - - migrationBuilder.CreateIndex( - name: "IX_product_skus_TenantId_SkuCode", - table: "product_skus", - columns: new[] { "TenantId", "SkuCode" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_products_TenantId_SpuCode", - table: "products", - columns: new[] { "TenantId", "SpuCode" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_products_TenantId_StoreId", - table: "products", - columns: new[] { "TenantId", "StoreId" }); - - migrationBuilder.CreateIndex( - name: "IX_queue_tickets_TenantId_StoreId", - table: "queue_tickets", - columns: new[] { "TenantId", "StoreId" }); - - migrationBuilder.CreateIndex( - name: "IX_queue_tickets_TenantId_StoreId_TicketNumber", - table: "queue_tickets", - columns: new[] { "TenantId", "StoreId", "TicketNumber" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_refund_requests_TenantId_RefundNo", - table: "refund_requests", - columns: new[] { "TenantId", "RefundNo" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_reservations_TenantId_ReservationNo", - table: "reservations", - columns: new[] { "TenantId", "ReservationNo" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_reservations_TenantId_StoreId", - table: "reservations", - columns: new[] { "TenantId", "StoreId" }); - - migrationBuilder.CreateIndex( - name: "IX_shopping_carts_TenantId_UserId_StoreId", - table: "shopping_carts", - columns: new[] { "TenantId", "UserId", "StoreId" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_store_business_hours_TenantId_StoreId_DayOfWeek", - table: "store_business_hours", - columns: new[] { "TenantId", "StoreId", "DayOfWeek" }); - - migrationBuilder.CreateIndex( - name: "IX_store_delivery_zones_TenantId_StoreId_ZoneName", - table: "store_delivery_zones", - columns: new[] { "TenantId", "StoreId", "ZoneName" }); - - migrationBuilder.CreateIndex( - name: "IX_store_employee_shifts_TenantId_StoreId_ShiftDate_StaffId", - table: "store_employee_shifts", - columns: new[] { "TenantId", "StoreId", "ShiftDate", "StaffId" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_store_holidays_TenantId_StoreId_Date", - table: "store_holidays", - columns: new[] { "TenantId", "StoreId", "Date" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_store_table_areas_TenantId_StoreId_Name", - table: "store_table_areas", - columns: new[] { "TenantId", "StoreId", "Name" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_store_tables_TenantId_StoreId_TableCode", - table: "store_tables", - columns: new[] { "TenantId", "StoreId", "TableCode" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_stores_TenantId_Code", - table: "stores", - columns: new[] { "TenantId", "Code" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_stores_TenantId_MerchantId", - table: "stores", - columns: new[] { "TenantId", "MerchantId" }); - - migrationBuilder.CreateIndex( - name: "IX_support_tickets_TenantId_TicketNo", - table: "support_tickets", - columns: new[] { "TenantId", "TicketNo" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_tenant_billing_statements_TenantId_StatementNo", - table: "tenant_billing_statements", - columns: new[] { "TenantId", "StatementNo" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_tenant_notifications_TenantId_Channel_SentAt", - table: "tenant_notifications", - columns: new[] { "TenantId", "Channel", "SentAt" }); - - migrationBuilder.CreateIndex( - name: "IX_tenant_quota_usages_TenantId_QuotaType", - table: "tenant_quota_usages", - columns: new[] { "TenantId", "QuotaType" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_tenant_subscriptions_TenantId_TenantPackageId", - table: "tenant_subscriptions", - columns: new[] { "TenantId", "TenantPackageId" }); - - migrationBuilder.CreateIndex( - name: "IX_tenants_Code", - table: "tenants", - column: "Code", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ticket_comments_TenantId_SupportTicketId", - table: "ticket_comments", - columns: new[] { "TenantId", "SupportTicketId" }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "affiliate_orders"); - - migrationBuilder.DropTable( - name: "affiliate_partners"); - - migrationBuilder.DropTable( - name: "affiliate_payouts"); - - migrationBuilder.DropTable( - name: "cart_item_addons"); - - migrationBuilder.DropTable( - name: "cart_items"); - - migrationBuilder.DropTable( - name: "chat_messages"); - - migrationBuilder.DropTable( - name: "chat_sessions"); - - migrationBuilder.DropTable( - name: "checkin_campaigns"); - - migrationBuilder.DropTable( - name: "checkin_records"); - - migrationBuilder.DropTable( - name: "checkout_sessions"); - - migrationBuilder.DropTable( - name: "community_comments"); - - migrationBuilder.DropTable( - name: "community_posts"); - - migrationBuilder.DropTable( - name: "community_reactions"); - - migrationBuilder.DropTable( - name: "coupon_templates"); - - migrationBuilder.DropTable( - name: "coupons"); - - migrationBuilder.DropTable( - name: "delivery_events"); - - migrationBuilder.DropTable( - name: "delivery_orders"); - - migrationBuilder.DropTable( - name: "group_orders"); - - migrationBuilder.DropTable( - name: "group_participants"); - - migrationBuilder.DropTable( - name: "inventory_adjustments"); - - migrationBuilder.DropTable( - name: "inventory_batches"); - - migrationBuilder.DropTable( - name: "inventory_items"); - - migrationBuilder.DropTable( - name: "map_locations"); - - migrationBuilder.DropTable( - name: "member_growth_logs"); - - migrationBuilder.DropTable( - name: "member_point_ledgers"); - - migrationBuilder.DropTable( - name: "member_profiles"); - - migrationBuilder.DropTable( - name: "member_tiers"); - - migrationBuilder.DropTable( - name: "merchant_contracts"); - - migrationBuilder.DropTable( - name: "merchant_documents"); - - migrationBuilder.DropTable( - name: "merchant_staff"); - - migrationBuilder.DropTable( - name: "merchants"); - - migrationBuilder.DropTable( - name: "metric_alert_rules"); - - migrationBuilder.DropTable( - name: "metric_definitions"); - - migrationBuilder.DropTable( - name: "metric_snapshots"); - - migrationBuilder.DropTable( - name: "navigation_requests"); - - migrationBuilder.DropTable( - name: "order_items"); - - migrationBuilder.DropTable( - name: "order_status_histories"); - - migrationBuilder.DropTable( - name: "payment_records"); - - migrationBuilder.DropTable( - name: "payment_refund_records"); - - migrationBuilder.DropTable( - name: "product_addon_groups"); - - migrationBuilder.DropTable( - name: "product_addon_options"); - - migrationBuilder.DropTable( - name: "product_attribute_groups"); - - migrationBuilder.DropTable( - name: "product_attribute_options"); - - migrationBuilder.DropTable( - name: "product_categories"); - - migrationBuilder.DropTable( - name: "product_media_assets"); - - migrationBuilder.DropTable( - name: "product_pricing_rules"); - - migrationBuilder.DropTable( - name: "product_skus"); - - migrationBuilder.DropTable( - name: "products"); - - migrationBuilder.DropTable( - name: "promotion_campaigns"); - - migrationBuilder.DropTable( - name: "queue_tickets"); - - migrationBuilder.DropTable( - name: "refund_requests"); - - migrationBuilder.DropTable( - name: "reservations"); - - migrationBuilder.DropTable( - name: "shopping_carts"); - - migrationBuilder.DropTable( - name: "store_business_hours"); - - migrationBuilder.DropTable( - name: "store_delivery_zones"); - - migrationBuilder.DropTable( - name: "store_employee_shifts"); - - migrationBuilder.DropTable( - name: "store_holidays"); - - migrationBuilder.DropTable( - name: "store_table_areas"); - - migrationBuilder.DropTable( - name: "store_tables"); - - migrationBuilder.DropTable( - name: "stores"); - - migrationBuilder.DropTable( - name: "support_tickets"); - - migrationBuilder.DropTable( - name: "tenant_billing_statements"); - - migrationBuilder.DropTable( - name: "tenant_notifications"); - - migrationBuilder.DropTable( - name: "tenant_packages"); - - migrationBuilder.DropTable( - name: "tenant_quota_usages"); - - migrationBuilder.DropTable( - name: "tenant_subscriptions"); - - migrationBuilder.DropTable( - name: "tenants"); - - migrationBuilder.DropTable( - name: "ticket_comments"); - - migrationBuilder.DropTable( - name: "orders"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251205113018_AddTenantVerificationProfile.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251205113018_AddTenantVerificationProfile.Designer.cs deleted file mode 100644 index 4e3fa03..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251205113018_AddTenantVerificationProfile.Designer.cs +++ /dev/null @@ -1,6673 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.App.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - [DbContext(typeof(TakeoutAppDbContext))] - [Migration("20251205113018_AddTenantVerificationProfile")] - partial class AddTenantVerificationProfile - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricAlertRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionJson") - .IsRequired() - .HasColumnType("text") - .HasComment("触发条件 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Enabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("关联指标。"); - - b.Property("NotificationChannels") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("通知渠道。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("告警级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "Severity"); - - b.ToTable("metric_alert_rules", null, t => - { - t.HasComment("指标告警规则。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricDefinition", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("指标编码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultAggregation") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("默认聚合方式。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("说明。"); - - b.Property("DimensionsJson") - .HasColumnType("text") - .HasComment("维度描述 JSON。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("指标名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("metric_definitions", null, t => - { - t.HasComment("指标定义,描述可观测的数据点。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricSnapshot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DimensionKey") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("维度键(JSON)。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("指标定义 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Value") - .HasPrecision(18, 4) - .HasColumnType("numeric(18,4)") - .HasComment("数值。"); - - b.Property("WindowEnd") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口结束。"); - - b.Property("WindowStart") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口开始。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "DimensionKey", "WindowStart", "WindowEnd") - .IsUnique(); - - b.ToTable("metric_snapshots", null, t => - { - t.HasComment("指标快照,用于大盘展示。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.Coupon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("券码或序列号。"); - - b.Property("CouponTemplateId") - .HasColumnType("bigint") - .HasComment("模板标识。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("发放时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID(已使用时记录)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedAt") - .HasColumnType("timestamp with time zone") - .HasComment("使用时间。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("归属用户。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("coupons", null, t => - { - t.HasComment("用户领取的券。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.CouponTemplate", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowStack") - .HasColumnType("boolean") - .HasComment("是否允许叠加其他优惠。"); - - b.Property("ChannelsJson") - .HasColumnType("text") - .HasComment("发放渠道(JSON)。"); - - b.Property("ClaimedQuantity") - .HasColumnType("integer") - .HasComment("已领取数量。"); - - b.Property("CouponType") - .HasColumnType("integer") - .HasComment("券类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("DiscountCap") - .HasColumnType("numeric") - .HasComment("折扣上限(针对折扣券)。"); - - b.Property("MinimumSpend") - .HasColumnType("numeric") - .HasComment("最低消费门槛。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("模板名称。"); - - b.Property("ProductScopeJson") - .HasColumnType("text") - .HasComment("适用品类或商品范围(JSON)。"); - - b.Property("RelativeValidDays") - .HasColumnType("integer") - .HasComment("有效天数(相对发放时间)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreScopeJson") - .HasColumnType("text") - .HasComment("适用门店 ID 集合(JSON)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TotalQuantity") - .HasColumnType("integer") - .HasComment("总发放数量上限。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ValidFrom") - .HasColumnType("timestamp with time zone") - .HasComment("可用开始时间。"); - - b.Property("ValidTo") - .HasColumnType("timestamp with time zone") - .HasComment("可用结束时间。"); - - b.Property("Value") - .HasColumnType("numeric") - .HasComment("面值或折扣额度。"); - - b.HasKey("Id"); - - b.ToTable("coupon_templates", null, t => - { - t.HasComment("优惠券模板。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.PromotionCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AudienceDescription") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("目标人群描述。"); - - b.Property("BannerUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营销素材(如 banner)。"); - - b.Property("Budget") - .HasColumnType("numeric") - .HasComment("预算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("PromotionType") - .HasColumnType("integer") - .HasComment("活动类型。"); - - b.Property("RulesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("活动规则 JSON。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("活动状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("promotion_campaigns", null, t => - { - t.HasComment("营销活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChatSessionId") - .HasColumnType("bigint") - .HasComment("会话标识。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("消息内容。"); - - b.Property("ContentType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("消息类型(文字/图片/语音等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRead") - .HasColumnType("boolean") - .HasComment("是否已读。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("读取时间。"); - - b.Property("SenderType") - .HasColumnType("integer") - .HasComment("发送方类型。"); - - b.Property("SenderUserId") - .HasColumnType("bigint") - .HasComment("发送方用户 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ChatSessionId", "CreatedAt"); - - b.ToTable("chat_messages", null, t => - { - t.HasComment("会话消息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AgentUserId") - .HasColumnType("bigint") - .HasComment("当前客服员工 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("顾客用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndedAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("IsBotActive") - .HasColumnType("boolean") - .HasComment("是否机器人接待中。"); - - b.Property("SessionCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话编号。"); - - b.Property("StartedAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店(可空为平台)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionCode") - .IsUnique(); - - b.ToTable("chat_sessions", null, t => - { - t.HasComment("客服会话。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.SupportTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AssignedAgentId") - .HasColumnType("bigint") - .HasComment("指派的客服。"); - - b.Property("ClosedAt") - .HasColumnType("timestamp with time zone") - .HasComment("关闭时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("客户用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .IsRequired() - .HasColumnType("text") - .HasComment("工单详情。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单(如有)。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("优先级。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("Subject") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("工单主题。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("工单编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TicketNo") - .IsUnique(); - - b.ToTable("support_tickets", null, t => - { - t.HasComment("客服工单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.TicketComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttachmentsJson") - .HasColumnType("text") - .HasComment("附件 JSON。"); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人 ID。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsInternal") - .HasColumnType("boolean") - .HasComment("是否内部备注。"); - - b.Property("SupportTicketId") - .HasColumnType("bigint") - .HasComment("工单标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SupportTicketId"); - - b.ToTable("ticket_comments", null, t => - { - t.HasComment("工单评论/流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryEvent", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryOrderId") - .HasColumnType("bigint") - .HasComment("配送单标识。"); - - b.Property("EventType") - .HasColumnType("integer") - .HasComment("事件类型。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("事件描述。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始数据 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DeliveryOrderId", "EventType"); - - b.ToTable("delivery_events", null, t => - { - t.HasComment("配送状态事件流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CourierName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("骑手姓名。"); - - b.Property("CourierPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("骑手电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveredAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("DispatchedAt") - .HasColumnType("timestamp with time zone") - .HasComment("下发时间。"); - - b.Property("FailureReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("异常原因。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("获取或设置关联订单 ID。"); - - b.Property("PickedUpAt") - .HasColumnType("timestamp with time zone") - .HasComment("取餐时间。"); - - b.Property("Provider") - .HasColumnType("integer") - .HasComment("配送服务商。"); - - b.Property("ProviderOrderId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方配送单号。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId") - .IsUnique(); - - b.ToTable("delivery_orders", null, t => - { - t.HasComment("配送单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliateOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("推广人标识。"); - - b.Property("BuyerUserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedCommission") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("预计佣金。"); - - b.Property("OrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("订单金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("SettledAt") - .HasColumnType("timestamp with time zone") - .HasComment("结算完成时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "OrderId") - .IsUnique(); - - b.ToTable("affiliate_orders", null, t => - { - t.HasComment("分销订单记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePartner", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChannelType") - .HasColumnType("integer") - .HasComment("渠道类型。"); - - b.Property("CommissionRate") - .HasColumnType("numeric") - .HasComment("分成比例(0-1)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称或渠道名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID(如绑定平台账号)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DisplayName"); - - b.ToTable("affiliate_partners", null, t => - { - t.HasComment("分销/推广合作伙伴。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePayout", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("合作伙伴标识。"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("结算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("打款时间。"); - - b.Property("Period") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("结算周期描述。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "Period") - .IsUnique(); - - b.ToTable("affiliate_payouts", null, t => - { - t.HasComment("佣金结算记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowMakeupCount") - .HasColumnType("integer") - .HasComment("支持补签次数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("活动描述。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("结束日期。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("RewardsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("连签奖励 JSON。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("开始日期。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name"); - - b.ToTable("checkin_campaigns", null, t => - { - t.HasComment("签到活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CheckInCampaignId") - .HasColumnType("bigint") - .HasComment("活动标识。"); - - b.Property("CheckInDate") - .HasColumnType("timestamp with time zone") - .HasComment("签到日期(本地)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsMakeup") - .HasColumnType("boolean") - .HasComment("是否补签。"); - - b.Property("RewardJson") - .IsRequired() - .HasColumnType("text") - .HasComment("获得奖励 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "CheckInCampaignId", "UserId", "CheckInDate") - .IsUnique(); - - b.ToTable("checkin_records", null, t => - { - t.HasComment("用户签到记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsDeleted") - .HasColumnType("boolean") - .HasComment("状态。"); - - b.Property("ParentId") - .HasColumnType("bigint") - .HasComment("父级评论 ID。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "CreatedAt"); - - b.ToTable("community_comments", null, t => - { - t.HasComment("社区评论。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityPost", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("作者用户 ID。"); - - b.Property("CommentCount") - .HasColumnType("integer") - .HasComment("评论数。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LikeCount") - .HasColumnType("integer") - .HasComment("点赞数。"); - - b.Property("MediaJson") - .HasColumnType("text") - .HasComment("媒体资源 JSON。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AuthorUserId", "CreatedAt"); - - b.ToTable("community_posts", null, t => - { - t.HasComment("社区动态。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityReaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态 ID。"); - - b.Property("ReactedAt") - .HasColumnType("timestamp with time zone") - .HasComment("时间戳。"); - - b.Property("ReactionType") - .HasColumnType("integer") - .HasComment("反应类型。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "UserId") - .IsUnique(); - - b.ToTable("community_reactions", null, t => - { - t.HasComment("社区互动反馈。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentCount") - .HasColumnType("integer") - .HasComment("当前已参与人数。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("GroupOrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("拼单编号。"); - - b.Property("GroupPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("拼团价格。"); - - b.Property("LeaderUserId") - .HasColumnType("bigint") - .HasComment("团长用户 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("关联商品或套餐。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("拼团状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("SucceededAt") - .HasColumnType("timestamp with time zone") - .HasComment("成团时间。"); - - b.Property("TargetCount") - .HasColumnType("integer") - .HasComment("成团需要的人数。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderNo") - .IsUnique(); - - b.ToTable("group_orders", null, t => - { - t.HasComment("拼单活动。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupParticipant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GroupOrderId") - .HasColumnType("bigint") - .HasComment("拼单活动标识。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("参与时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("对应订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("参与状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderId", "UserId") - .IsUnique(); - - b.ToTable("group_participants", null, t => - { - t.HasComment("拼单参与者。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryAdjustment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdjustmentType") - .HasColumnType("integer") - .HasComment("调整类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("InventoryItemId") - .HasColumnType("bigint") - .HasComment("对应的库存记录标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("调整数量,正数增加,负数减少。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("原因说明。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "InventoryItemId", "OccurredAt"); - - b.ToTable("inventory_adjustments", null, t => - { - t.HasComment("库存调整记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryBatch", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("ProductionDate") - .HasColumnType("timestamp with time zone") - .HasComment("生产日期。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("入库数量。"); - - b.Property("RemainingQuantity") - .HasColumnType("integer") - .HasComment("剩余数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber") - .IsUnique(); - - b.ToTable("inventory_batches", null, t => - { - t.HasComment("SKU 批次信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchConsumeStrategy") - .HasColumnType("integer") - .HasComment("批次扣减策略。"); - - b.Property("BatchNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号,可为空表示混批。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售商品。"); - - b.Property("IsSoldOut") - .HasColumnType("boolean") - .HasComment("是否标记售罄。"); - - b.Property("Location") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("储位或仓位信息。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单品限购(覆盖商品级 MaxQuantityPerOrder)。"); - - b.Property("PresaleCapacity") - .HasColumnType("integer") - .HasComment("预售名额(上限)。"); - - b.Property("PresaleEndTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售结束时间(UTC)。"); - - b.Property("PresaleLocked") - .HasColumnType("integer") - .HasComment("当前预售已锁定数量。"); - - b.Property("PresaleStartTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售开始时间(UTC)。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("QuantityOnHand") - .HasColumnType("integer") - .HasComment("可用库存。"); - - b.Property("QuantityReserved") - .HasColumnType("integer") - .HasComment("已锁定库存(订单占用)。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("SafetyStock") - .HasColumnType("integer") - .HasComment("安全库存阈值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber"); - - b.ToTable("inventory_items", null, t => - { - t.HasComment("SKU 在门店的库存信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryLockRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("IdempotencyKey") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("幂等键。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售锁定。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU ID。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("锁定数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("锁定状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "IdempotencyKey") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "Status"); - - b.ToTable("inventory_lock_records", null, t => - { - t.HasComment("库存锁定记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberGrowthLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChangeValue") - .HasColumnType("integer") - .HasComment("变动数量。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentValue") - .HasColumnType("integer") - .HasComment("当前成长值。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_growth_logs", null, t => - { - t.HasComment("成长值变动日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberPointLedger", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BalanceAfterChange") - .HasColumnType("integer") - .HasComment("变动后余额。"); - - b.Property("ChangeAmount") - .HasColumnType("integer") - .HasComment("变动数量,可为负值。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(如适用)。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Reason") - .HasColumnType("integer") - .HasComment("变动原因。"); - - b.Property("SourceId") - .HasColumnType("bigint") - .HasComment("来源 ID(订单、活动等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_point_ledgers", null, t => - { - t.HasComment("积分变动流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AvatarUrl") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像。"); - - b.Property("BirthDate") - .HasColumnType("timestamp with time zone") - .HasComment("生日。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GrowthValue") - .HasColumnType("integer") - .HasComment("成长值/经验值。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("注册时间。"); - - b.Property("MemberTierId") - .HasColumnType("bigint") - .HasComment("当前会员等级 ID。"); - - b.Property("Mobile") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("Nickname") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称。"); - - b.Property("PointsBalance") - .HasColumnType("integer") - .HasComment("会员积分余额。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会员状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Mobile") - .IsUnique(); - - b.ToTable("member_profiles", null, t => - { - t.HasComment("会员档案。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberTier", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BenefitsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("等级权益(JSON)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("等级名称。"); - - b.Property("RequiredGrowth") - .HasColumnType("integer") - .HasComment("所需成长值。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("member_tiers", null, t => - { - t.HasComment("会员等级定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.Merchant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("BrandAlias") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("品牌简称或别名。"); - - b.Property("BrandName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("品牌名称(对外展示)。"); - - b.Property("BusinessLicenseImageUrl") - .HasColumnType("text") - .HasComment("营业执照扫描件地址。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照号。"); - - b.Property("Category") - .HasColumnType("text") - .HasComment("品牌所属品类,如火锅、咖啡等。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("联系邮箱。"); - - b.Property("ContactPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在区县。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("入驻时间。"); - - b.Property("LastReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次审核时间。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度信息。"); - - b.Property("LegalPerson") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人或负责人姓名。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("品牌 Logo。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度信息。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注或驳回原因。"); - - b.Property("ServicePhone") - .HasColumnType("text") - .HasComment("客服电话。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("入驻状态。"); - - b.Property("SupportEmail") - .HasColumnType("text") - .HasComment("客服邮箱。"); - - b.Property("TaxNumber") - .HasColumnType("text") - .HasComment("税号/统一社会信用代码。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.ToTable("merchants", null, t => - { - t.HasComment("商户主体信息,承载入驻和资质审核结果。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantAuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("动作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("详情描述。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("商户标识。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId"); - - b.ToTable("merchant_audit_logs", null, t => - { - t.HasComment("商户入驻审核日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("显示顺序,越小越靠前。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否可用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("类目名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("merchant_categories", null, t => - { - t.HasComment("商户可选类目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantContract", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ContractNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("合同编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同结束时间。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("合同文件存储地址。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("SignedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签署时间。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("合同状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TerminatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("终止时间。"); - - b.Property("TerminationReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("终止原因。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "ContractNumber") - .IsUnique(); - - b.ToTable("merchant_contracts", null, t => - { - t.HasComment("商户合同记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantDocument", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DocumentNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("证照编号。"); - - b.Property("DocumentType") - .HasColumnType("integer") - .HasComment("证照类型。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期日期。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("证照文件链接。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签发日期。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Remarks") - .HasColumnType("text") - .HasComment("审核备注或驳回原因。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("审核状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "DocumentType"); - - b.ToTable("merchant_documents", null, t => - { - t.HasComment("商户提交的资质或证照材料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantStaff", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Email") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("邮箱地址。"); - - b.Property("IdentityUserId") - .HasColumnType("bigint") - .HasComment("登录账号 ID(指向统一身份体系)。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("员工姓名。"); - - b.Property("PermissionsJson") - .HasColumnType("text") - .HasComment("自定义权限(JSON)。"); - - b.Property("Phone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("员工角色类型。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("员工状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("可选的关联门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "Phone"); - - b.ToTable("merchant_staff", null, t => - { - t.HasComment("商户员工账号,支持门店维度分配。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.MapLocation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Landmark") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("打车/导航落点描述。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("名称。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店 ID,可空表示独立 POI。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("map_locations", null, t => - { - t.HasComment("地图 POI 信息,用于门店定位和推荐。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.NavigationRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("来源通道(小程序、H5 等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("请求时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TargetApp") - .HasColumnType("integer") - .HasComment("跳转的地图应用。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId", "RequestedAt"); - - b.ToTable("navigation_requests", null, t => - { - t.HasComment("用户发起的导航请求日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("扩展 JSON(规格、加料选项等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品或 SKU 标识。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称快照。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("自定义备注(口味要求)。"); - - b.Property("ShoppingCartId") - .HasColumnType("bigint") - .HasComment("所属购物车标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价快照。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ShoppingCartId"); - - b.ToTable("cart_items", null, t => - { - t.HasComment("购物车条目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItemAddon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CartItemId") - .HasColumnType("bigint") - .HasComment("所属购物车条目。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("OptionId") - .HasColumnType("bigint") - .HasComment("选项 ID(可对应 ProductAddonOption)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("cart_item_addons", null, t => - { - t.HasComment("购物车条目的加料/附加项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CheckoutSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("SessionToken") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话 Token。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.Property("ValidationResultJson") - .IsRequired() - .HasColumnType("text") - .HasComment("校验结果明细 JSON。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionToken") - .IsUnique(); - - b.ToTable("checkout_sessions", null, t => - { - t.HasComment("结账会话,记录校验上下文。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.ShoppingCart", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryPreference") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("履约方式(堂食/自提/配送)缓存。"); - - b.Property("LastModifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次修改时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("购物车状态,包含正常/锁定。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableContext") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌码或场景标识(扫码点餐)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId") - .IsUnique(); - - b.ToTable("shopping_carts", null, t => - { - t.HasComment("用户购物车,按租户/门店隔离。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.Order", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("取消原因。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("下单渠道。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("顾客姓名。"); - - b.Property("CustomerPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("顾客手机号。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryType") - .HasColumnType("integer") - .HasComment("履约类型。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("优惠金额。"); - - b.Property("FinishedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("ItemsAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("商品总额。"); - - b.Property("OrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("订单号。"); - - b.Property("PaidAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付时间。"); - - b.Property("PayableAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额。"); - - b.Property("PaymentStatus") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("QueueNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队号(如有)。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationId") - .HasColumnType("bigint") - .HasComment("预约 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TableNo") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("就餐桌号。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "Status"); - - b.ToTable("orders", null, t => - { - t.HasComment("交易订单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("自定义属性 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("折扣金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品 ID。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("SkuName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("SKU/规格描述。"); - - b.Property("SubTotal") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("小计。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("单位。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("OrderId"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("order_items", null, t => - { - t.HasComment("订单明细。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderStatusHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注信息。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识(可为空表示系统)。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("变更后的状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId", "OccurredAt"); - - b.ToTable("order_status_histories", null, t => - { - t.HasComment("订单状态流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.RefundRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("申请金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("ProcessedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核完成时间。"); - - b.Property("Reason") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("申请原因。"); - - b.Property("RefundNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("退款单号。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("用户提交时间。"); - - b.Property("ReviewNotes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "RefundNo") - .IsUnique(); - - b.ToTable("refund_requests", null, t => - { - t.HasComment("售后/退款申请。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("支付金额。"); - - b.Property("ChannelTransactionId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方渠道单号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Method") - .HasColumnType("integer") - .HasComment("支付方式。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付完成时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始回调内容。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("错误/备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TradeNo") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("平台交易号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("payment_records", null, t => - { - t.HasComment("支付流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRefundRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("退款金额。"); - - b.Property("ChannelRefundId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("渠道退款流水号。"); - - b.Property("CompletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("渠道返回的原始数据 JSON。"); - - b.Property("PaymentRecordId") - .HasColumnType("bigint") - .HasComment("原支付记录标识。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("退款请求时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PaymentRecordId"); - - b.ToTable("payment_refund_records", null, t => - { - t.HasComment("支付渠道退款流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.Product", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CategoryId") - .HasColumnType("bigint") - .HasComment("所属分类。"); - - b.Property("CoverImage") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("主图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("商品描述。"); - - b.Property("EnableDelivery") - .HasColumnType("boolean") - .HasComment("支持配送。"); - - b.Property("EnableDineIn") - .HasColumnType("boolean") - .HasComment("支持堂食。"); - - b.Property("EnablePickup") - .HasColumnType("boolean") - .HasComment("支持自提。"); - - b.Property("GalleryImages") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Gallery 图片逗号分隔。"); - - b.Property("IsFeatured") - .HasColumnType("boolean") - .HasComment("是否热门推荐。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("最大每单限购。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("现价。"); - - b.Property("SpuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("商品编码。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("商品状态。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("库存数量(可选)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("Subtitle") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("副标题/卖点。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("售卖单位(份/杯等)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SpuCode") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("products", null, t => - { - t.HasComment("商品(SPU)信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("MaxSelect") - .HasColumnType("integer") - .HasComment("最大选择数量。"); - - b.Property("MinSelect") - .HasColumnType("integer") - .HasComment("最小选择数量。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "Name"); - - b.ToTable("product_addon_groups", null, t => - { - t.HasComment("加料/做法分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AddonGroupId") - .HasColumnType("bigint") - .HasComment("所属加料分组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选项。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("product_addon_options", null, t => - { - t.HasComment("加料选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称,例如“辣度”“份量”。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型(单选/多选)。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("显示排序。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店,可为空表示所有门店共享。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("product_attribute_groups", null, t => - { - t.HasComment("商品规格/属性分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributeGroupId") - .HasColumnType("bigint") - .HasComment("所属规格组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选中。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AttributeGroupId", "Name") - .IsUnique(); - - b.ToTable("product_attribute_options", null, t => - { - t.HasComment("商品规格选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("分类描述。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分类名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("product_categories", null, t => - { - t.HasComment("商品分类。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductMediaAsset", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Caption") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述或标题。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MediaType") - .HasColumnType("integer") - .HasComment("媒体类型。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品标识。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Url") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("媒资链接。"); - - b.HasKey("Id"); - - b.ToTable("product_media_assets", null, t => - { - t.HasComment("商品媒资素材。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductPricingRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("条件描述(JSON),如会员等级、渠道等。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效结束时间。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("特殊价格。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("RuleType") - .HasColumnType("integer") - .HasComment("策略类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StartTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效开始时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("WeekdaysJson") - .HasColumnType("text") - .HasComment("生效星期(JSON 数组)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "RuleType"); - - b.ToTable("product_pricing_rules", null, t => - { - t.HasComment("商品价格策略,支持会员价/时段价等。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductSku", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("规格属性 JSON(记录选项 ID)。"); - - b.Property("Barcode") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("条形码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("售价。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SkuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("SKU 编码。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("可售库存。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weight") - .HasPrecision(10, 3) - .HasColumnType("numeric(10,3)") - .HasComment("重量(千克)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SkuCode") - .IsUnique(); - - b.ToTable("product_skus", null, t => - { - t.HasComment("商品 SKU,记录具体规格组合价格。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Queues.Entities.QueueTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CalledAt") - .HasColumnType("timestamp with time zone") - .HasComment("叫号时间。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedWaitMinutes") - .HasColumnType("integer") - .HasComment("预计等待分钟。"); - - b.Property("ExpiredAt") - .HasColumnType("timestamp with time zone") - .HasComment("过号时间。"); - - b.Property("PartySize") - .HasColumnType("integer") - .HasComment("就餐人数。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("获取或设置所属门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNumber") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.HasIndex("TenantId", "StoreId", "TicketNumber") - .IsUnique(); - - b.ToTable("queue_tickets", null, t => - { - t.HasComment("排队叫号。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Reservations.Entities.Reservation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CheckInCode") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("核销码/到店码。"); - - b.Property("CheckedInAt") - .HasColumnType("timestamp with time zone") - .HasComment("实际签到时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("客户姓名。"); - - b.Property("CustomerPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PeopleCount") - .HasColumnType("integer") - .HasComment("用餐人数。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("预约号。"); - - b.Property("ReservationTime") - .HasColumnType("timestamp with time zone") - .HasComment("预约时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TablePreference") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌型/标签。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ReservationNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("reservations", null, t => - { - t.HasComment("预约/预订记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.Store", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("Announcement") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("门店公告。"); - - b.Property("BusinessHours") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("门店营业时段描述(备用字符串)。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("门店编码,便于扫码及外部对接。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家或地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("门店海报。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryRadiusKm") - .HasPrecision(6, 2) - .HasColumnType("numeric(6,2)") - .HasComment("默认配送半径(公里)。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("门店描述或公告。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区县信息。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("高德/腾讯地图经度。"); - - b.Property("ManagerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("门店负责人姓名。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("门店名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("门店当前运营状态。"); - - b.Property("SupportsDelivery") - .HasColumnType("boolean") - .HasComment("是否支持配送。"); - - b.Property("SupportsDineIn") - .HasColumnType("boolean") - .HasComment("是否支持堂食。"); - - b.Property("SupportsPickup") - .HasColumnType("boolean") - .HasComment("是否支持自提。"); - - b.Property("SupportsQueueing") - .HasColumnType("boolean") - .HasComment("支持排队叫号。"); - - b.Property("SupportsReservation") - .HasColumnType("boolean") - .HasComment("支持预约。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("门店标签(逗号分隔)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.HasIndex("TenantId", "MerchantId"); - - b.ToTable("stores", null, t => - { - t.HasComment("门店信息,承载营业配置与能力。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreBusinessHour", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CapacityLimit") - .HasColumnType("integer") - .HasComment("最大接待容量或单量限制。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DayOfWeek") - .HasColumnType("integer") - .HasComment("星期几,0 表示周日。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间(本地时间)。"); - - b.Property("HourType") - .HasColumnType("integer") - .HasComment("时段类型(正常营业、休息、预约等)。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间(本地时间)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "DayOfWeek"); - - b.ToTable("store_business_hours", null, t => - { - t.HasComment("门店营业时段配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreDeliveryZone", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("EstimatedMinutes") - .HasColumnType("integer") - .HasComment("预计送达分钟。"); - - b.Property("MinimumOrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("起送价。"); - - b.Property("PolygonGeoJson") - .IsRequired() - .HasColumnType("text") - .HasComment("GeoJSON 表示的多边形范围。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ZoneName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ZoneName"); - - b.ToTable("store_delivery_zones", null, t => - { - t.HasComment("门店配送范围配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreEmployeeShift", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("排班角色。"); - - b.Property("ShiftDate") - .HasColumnType("timestamp with time zone") - .HasComment("班次日期。"); - - b.Property("StaffId") - .HasColumnType("bigint") - .HasComment("员工标识。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ShiftDate", "StaffId") - .IsUnique(); - - b.ToTable("store_employee_shifts", null, t => - { - t.HasComment("门店员工排班记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreHoliday", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Date") - .HasColumnType("timestamp with time zone") - .HasComment("日期。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsClosed") - .HasColumnType("boolean") - .HasComment("是否全天闭店。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("说明内容。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Date") - .IsUnique(); - - b.ToTable("store_holidays", null, t => - { - t.HasComment("门店休息日或特殊营业日。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSetting", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowDaysAhead") - .HasColumnType("integer") - .HasComment("可预约天数(含当天)。"); - - b.Property("AllowToday") - .HasColumnType("boolean") - .HasComment("是否允许当天自提。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultCutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("默认截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单笔自提最大份数。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId") - .IsUnique(); - - b.ToTable("store_pickup_settings", null, t => - { - t.HasComment("门店自提配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSlot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("容量(份数)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("当天结束时间(UTC)。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("档期名称。"); - - b.Property("ReservedCount") - .HasColumnType("integer") - .HasComment("已占用数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("当天开始时间(UTC)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weekdays") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("适用星期(逗号分隔 1-7)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("store_pickup_slots", null, t => - { - t.HasComment("门店自提档期。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTable", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AreaId") - .HasColumnType("bigint") - .HasComment("所在区域 ID。"); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("可容纳人数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("QrCodeUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("桌码二维码地址。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前桌台状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("桌码。"); - - b.Property("Tags") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("桌台标签(堂食、快餐等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "TableCode") - .IsUnique(); - - b.ToTable("store_tables", null, t => - { - t.HasComment("桌台信息与二维码绑定。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTableArea", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("区域描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name") - .IsUnique(); - - b.ToTable("store_table_areas", null, t => - { - t.HasComment("门店桌台区域配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.Tenant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("text") - .HasComment("详细地址信息。"); - - b.Property("City") - .HasColumnType("text") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("租户短编码,作为跨系统引用的唯一标识。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("主联系人邮箱。"); - - b.Property("ContactName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("主联系人姓名。"); - - b.Property("ContactPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("主联系人电话。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家/地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("品牌海报或封面图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("服务生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("服务到期时间(UTC)。"); - - b.Property("Industry") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所属行业,如餐饮、零售等。"); - - b.Property("LegalEntityName") - .HasColumnType("text") - .HasComment("法人或公司主体名称。"); - - b.Property("LogoUrl") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("LOGO 图片地址。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("租户全称或品牌名称。"); - - b.Property("PrimaryOwnerUserId") - .HasColumnType("bigint") - .HasComment("系统内对应的租户所有者账号 ID。"); - - b.Property("Province") - .HasColumnType("text") - .HasComment("所在省份或州。"); - - b.Property("Remarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息,用于运营记录特殊说明。"); - - b.Property("ShortName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("对外展示的简称。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("租户当前状态,涵盖审核、启用、停用等场景。"); - - b.Property("SuspendedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次暂停服务时间。"); - - b.Property("SuspensionReason") - .HasColumnType("text") - .HasComment("暂停或终止的原因说明。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("业务标签集合(逗号分隔)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Website") - .HasColumnType("text") - .HasComment("官网或主要宣传链接。"); - - b.HasKey("Id"); - - b.HasIndex("Code") - .IsUnique(); - - b.ToTable("tenants", null, t => - { - t.HasComment("平台租户信息,描述租户的生命周期与基础资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementType") - .HasColumnType("integer") - .HasComment("公告类型。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("公告正文(可为 Markdown/HTML,前端自行渲染)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("失效时间(UTC),为空表示长期有效。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("展示优先级,数值越大越靠前。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("公告标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AnnouncementType", "IsActive"); - - b.HasIndex("TenantId", "EffectiveFrom", "EffectiveTo"); - - b.ToTable("tenant_announcements", null, t => - { - t.HasComment("租户公告。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncementRead", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementId") - .HasColumnType("bigint") - .HasComment("公告 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("已读时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("已读用户 ID(后台账号),为空表示租户级已读。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AnnouncementId", "UserId") - .IsUnique(); - - b.ToTable("tenant_announcement_reads", null, t => - { - t.HasComment("租户公告已读记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("操作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentStatus") - .HasColumnType("integer") - .HasComment("新状态。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("详细描述。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人名称。"); - - b.Property("PreviousStatus") - .HasColumnType("integer") - .HasComment("原状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("关联的租户标识。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("日志标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.ToTable("tenant_audit_logs", null, t => - { - t.HasComment("租户运营审核日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantBillingStatement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AmountDue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额。"); - - b.Property("AmountPaid") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DueDate") - .HasColumnType("timestamp with time zone") - .HasComment("到期日。"); - - b.Property("LineItemsJson") - .HasColumnType("text") - .HasComment("账单明细 JSON,记录各项费用。"); - - b.Property("PeriodEnd") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期结束时间。"); - - b.Property("PeriodStart") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期开始时间。"); - - b.Property("StatementNo") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("账单编号,供对账查询。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前付款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StatementNo") - .IsUnique(); - - b.ToTable("tenant_billing_statements", null, t => - { - t.HasComment("租户账单,用于呈现周期性收费。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantNotification", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("发布通道(站内、邮件、短信等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("通知正文。"); - - b.Property("MetadataJson") - .HasColumnType("text") - .HasComment("附加元数据 JSON。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("租户是否已阅读。"); - - b.Property("SentAt") - .HasColumnType("timestamp with time zone") - .HasComment("推送时间。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("通知重要级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("通知标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Channel", "SentAt"); - - b.ToTable("tenant_notifications", null, t => - { - t.HasComment("面向租户的站内通知或消息推送。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantPackage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("套餐描述,包含适用场景、权益等。"); - - b.Property("FeaturePoliciesJson") - .HasColumnType("text") - .HasComment("权益明细 JSON,记录自定义特性开关。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否仍可售卖。"); - - b.Property("MaxAccountCount") - .HasColumnType("integer") - .HasComment("允许创建的最大账号数。"); - - b.Property("MaxDeliveryOrders") - .HasColumnType("integer") - .HasComment("每月可调用的配送单数量上限。"); - - b.Property("MaxSmsCredits") - .HasColumnType("integer") - .HasComment("每月短信额度上限。"); - - b.Property("MaxStorageGb") - .HasColumnType("integer") - .HasComment("存储容量上限(GB)。"); - - b.Property("MaxStoreCount") - .HasColumnType("integer") - .HasComment("允许的最大门店数。"); - - b.Property("MonthlyPrice") - .HasColumnType("numeric") - .HasComment("月付价格,单位:人民币元。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("套餐名称,展示给租户的简称。"); - - b.Property("PackageType") - .HasColumnType("integer") - .HasComment("套餐分类(试用、标准、旗舰等)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("YearlyPrice") - .HasColumnType("numeric") - .HasComment("年付价格,单位:人民币元。"); - - b.HasKey("Id"); - - b.ToTable("tenant_packages", null, t => - { - t.HasComment("平台提供的租户套餐定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaUsage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LastResetAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次重置时间。"); - - b.Property("LimitValue") - .HasColumnType("numeric") - .HasComment("当前配额上限。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型,例如门店数、短信条数等。"); - - b.Property("ResetCycle") - .HasColumnType("text") - .HasComment("配额刷新周期描述(如月、年)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedValue") - .HasColumnType("numeric") - .HasComment("已消耗的数量。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "QuotaType") - .IsUnique(); - - b.ToTable("tenant_quota_usages", null, t => - { - t.HasComment("租户配额使用情况快照。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscription", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AutoRenew") - .HasColumnType("boolean") - .HasComment("是否开启自动续费。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("订阅生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("订阅到期时间(UTC)。"); - - b.Property("NextBillingDate") - .HasColumnType("timestamp with time zone") - .HasComment("下一个计费时间,配合自动续费使用。"); - - b.Property("Notes") - .HasColumnType("text") - .HasComment("运营备注信息。"); - - b.Property("ScheduledPackageId") - .HasColumnType("bigint") - .HasComment("若已排期升降配,对应的新套餐 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("订阅当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TenantPackageId") - .HasColumnType("bigint") - .HasComment("当前订阅关联的套餐标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantPackageId"); - - b.ToTable("tenant_subscriptions", null, t => - { - t.HasComment("租户套餐订阅记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscriptionHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasColumnType("numeric") - .HasComment("相关费用。"); - - b.Property("ChangeType") - .HasColumnType("integer") - .HasComment("变更类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Currency") - .HasMaxLength(8) - .HasColumnType("character varying(8)") - .HasComment("币种。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("FromPackageId") - .HasColumnType("bigint") - .HasComment("原套餐 ID。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("租户标识。"); - - b.Property("TenantSubscriptionId") - .HasColumnType("bigint") - .HasComment("对应的订阅 ID。"); - - b.Property("ToPackageId") - .HasColumnType("bigint") - .HasComment("新套餐 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantSubscriptionId"); - - b.ToTable("tenant_subscription_histories", null, t => - { - t.HasComment("租户套餐订阅变更记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantVerificationProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdditionalDataJson") - .HasColumnType("text") - .HasComment("附加资料(JSON)。"); - - b.Property("BankAccountName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("开户名。"); - - b.Property("BankAccountNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("银行账号。"); - - b.Property("BankName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("银行名称。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照编号。"); - - b.Property("BusinessLicenseUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营业执照文件地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LegalPersonIdBackUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证反面。"); - - b.Property("LegalPersonIdFrontUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证正面。"); - - b.Property("LegalPersonIdNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("法人身份证号。"); - - b.Property("LegalPersonName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人姓名。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注。"); - - b.Property("ReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核时间。"); - - b.Property("ReviewedBy") - .HasColumnType("bigint") - .HasComment("审核人 ID。"); - - b.Property("ReviewedByName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("审核人姓名。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("实名状态。"); - - b.Property("SubmittedAt") - .HasColumnType("timestamp with time zone") - .HasComment("提交时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("对应的租户标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId") - .IsUnique(); - - b.ToTable("tenant_verification_profiles", null, t => - { - t.HasComment("租户实名认证资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.HasOne("TakeoutSaaS.Domain.Orders.Entities.Order", null) - .WithMany() - .HasForeignKey("OrderId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251205113018_AddTenantVerificationProfile.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251205113018_AddTenantVerificationProfile.cs deleted file mode 100644 index 107f741..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251205113018_AddTenantVerificationProfile.cs +++ /dev/null @@ -1,544 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - /// - public partial class AddTenantVerificationProfile : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "StoreId", - table: "queue_tickets", - type: "bigint", - nullable: false, - comment: "获取或设置所属门店 ID。", - oldClrType: typeof(long), - oldType: "bigint"); - - migrationBuilder.AddColumn( - name: "BatchConsumeStrategy", - table: "inventory_items", - type: "integer", - nullable: false, - defaultValue: 0, - comment: "批次扣减策略。"); - - migrationBuilder.AddColumn( - name: "IsPresale", - table: "inventory_items", - type: "boolean", - nullable: false, - defaultValue: false, - comment: "是否预售商品。"); - - migrationBuilder.AddColumn( - name: "IsSoldOut", - table: "inventory_items", - type: "boolean", - nullable: false, - defaultValue: false, - comment: "是否标记售罄。"); - - migrationBuilder.AddColumn( - name: "MaxQuantityPerOrder", - table: "inventory_items", - type: "integer", - nullable: true, - comment: "单品限购(覆盖商品级 MaxQuantityPerOrder)。"); - - migrationBuilder.AddColumn( - name: "PresaleCapacity", - table: "inventory_items", - type: "integer", - nullable: true, - comment: "预售名额(上限)。"); - - migrationBuilder.AddColumn( - name: "PresaleEndTime", - table: "inventory_items", - type: "timestamp with time zone", - nullable: true, - comment: "预售结束时间(UTC)。"); - - migrationBuilder.AddColumn( - name: "PresaleLocked", - table: "inventory_items", - type: "integer", - nullable: false, - defaultValue: 0, - comment: "当前预售已锁定数量。"); - - migrationBuilder.AddColumn( - name: "PresaleStartTime", - table: "inventory_items", - type: "timestamp with time zone", - nullable: true, - comment: "预售开始时间(UTC)。"); - - migrationBuilder.AddColumn( - name: "RowVersion", - table: "inventory_items", - type: "bytea", - rowVersion: true, - nullable: false, - defaultValue: new byte[0], - comment: "并发控制字段。"); - - migrationBuilder.AddColumn( - name: "RowVersion", - table: "inventory_batches", - type: "bytea", - rowVersion: true, - nullable: false, - defaultValue: new byte[0], - comment: "并发控制字段。"); - - migrationBuilder.AlterColumn( - name: "OrderId", - table: "delivery_orders", - type: "bigint", - nullable: false, - comment: "获取或设置关联订单 ID。", - oldClrType: typeof(long), - oldType: "bigint"); - - migrationBuilder.CreateTable( - name: "inventory_lock_records", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - StoreId = table.Column(type: "bigint", nullable: false, comment: "门店 ID。"), - ProductSkuId = table.Column(type: "bigint", nullable: false, comment: "SKU ID。"), - Quantity = table.Column(type: "integer", nullable: false, comment: "锁定数量。"), - IsPresale = table.Column(type: "boolean", nullable: false, comment: "是否预售锁定。"), - IdempotencyKey = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, comment: "幂等键。"), - ExpiresAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "过期时间(UTC)。"), - Status = table.Column(type: "integer", nullable: false, comment: "锁定状态。"), - RowVersion = table.Column(type: "bytea", rowVersion: true, nullable: false, comment: "并发控制字段。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_inventory_lock_records", x => x.Id); - }, - comment: "库存锁定记录。"); - - migrationBuilder.CreateTable( - name: "merchant_audit_logs", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - MerchantId = table.Column(type: "bigint", nullable: false, comment: "商户标识。"), - Action = table.Column(type: "integer", nullable: false, comment: "动作类型。"), - Title = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, comment: "标题。"), - Description = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true, comment: "详情描述。"), - OperatorId = table.Column(type: "bigint", nullable: true, comment: "操作人 ID。"), - OperatorName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "操作人名称。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_merchant_audit_logs", x => x.Id); - }, - comment: "商户入驻审核日志。"); - - migrationBuilder.CreateTable( - name: "merchant_categories", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "类目名称。"), - DisplayOrder = table.Column(type: "integer", nullable: false, defaultValue: 0, comment: "显示顺序,越小越靠前。"), - IsActive = table.Column(type: "boolean", nullable: false, comment: "是否可用。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_merchant_categories", x => x.Id); - }, - comment: "商户可选类目。"); - - migrationBuilder.CreateTable( - name: "store_pickup_settings", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - StoreId = table.Column(type: "bigint", nullable: false, comment: "门店标识。"), - AllowToday = table.Column(type: "boolean", nullable: false, comment: "是否允许当天自提。"), - AllowDaysAhead = table.Column(type: "integer", nullable: false, comment: "可预约天数(含当天)。"), - DefaultCutoffMinutes = table.Column(type: "integer", nullable: false, defaultValue: 30, comment: "默认截单分钟(开始前多少分钟截止)。"), - MaxQuantityPerOrder = table.Column(type: "integer", nullable: true, comment: "单笔自提最大份数。"), - RowVersion = table.Column(type: "bytea", rowVersion: true, nullable: false, comment: "并发控制字段。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_store_pickup_settings", x => x.Id); - }, - comment: "门店自提配置。"); - - migrationBuilder.CreateTable( - name: "store_pickup_slots", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - StoreId = table.Column(type: "bigint", nullable: false, comment: "门店标识。"), - Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "档期名称。"), - StartTime = table.Column(type: "interval", nullable: false, comment: "当天开始时间(UTC)。"), - EndTime = table.Column(type: "interval", nullable: false, comment: "当天结束时间(UTC)。"), - CutoffMinutes = table.Column(type: "integer", nullable: false, defaultValue: 30, comment: "截单分钟(开始前多少分钟截止)。"), - Capacity = table.Column(type: "integer", nullable: false, comment: "容量(份数)。"), - ReservedCount = table.Column(type: "integer", nullable: false, comment: "已占用数量。"), - Weekdays = table.Column(type: "character varying(32)", maxLength: 32, nullable: false, comment: "适用星期(逗号分隔 1-7)。"), - IsEnabled = table.Column(type: "boolean", nullable: false, comment: "是否启用。"), - RowVersion = table.Column(type: "bytea", rowVersion: true, nullable: false, comment: "并发控制字段。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_store_pickup_slots", x => x.Id); - }, - comment: "门店自提档期。"); - - migrationBuilder.CreateTable( - name: "tenant_announcement_reads", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - AnnouncementId = table.Column(type: "bigint", nullable: false, comment: "公告 ID。"), - UserId = table.Column(type: "bigint", nullable: true, comment: "已读用户 ID(后台账号),为空表示租户级已读。"), - ReadAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "已读时间。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_tenant_announcement_reads", x => x.Id); - }, - comment: "租户公告已读记录。"); - - migrationBuilder.CreateTable( - name: "tenant_announcements", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - Title = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, comment: "公告标题。"), - Content = table.Column(type: "text", nullable: false, comment: "公告正文(可为 Markdown/HTML,前端自行渲染)。"), - AnnouncementType = table.Column(type: "integer", nullable: false, comment: "公告类型。"), - Priority = table.Column(type: "integer", nullable: false, comment: "展示优先级,数值越大越靠前。"), - EffectiveFrom = table.Column(type: "timestamp with time zone", nullable: false, comment: "生效时间(UTC)。"), - EffectiveTo = table.Column(type: "timestamp with time zone", nullable: true, comment: "失效时间(UTC),为空表示长期有效。"), - IsActive = table.Column(type: "boolean", nullable: false, comment: "是否启用。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_tenant_announcements", x => x.Id); - }, - comment: "租户公告。"); - - migrationBuilder.CreateTable( - name: "tenant_audit_logs", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - TenantId = table.Column(type: "bigint", nullable: false, comment: "关联的租户标识。"), - Action = table.Column(type: "integer", nullable: false, comment: "操作类型。"), - Title = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, comment: "日志标题。"), - Description = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true, comment: "详细描述。"), - OperatorId = table.Column(type: "bigint", nullable: true, comment: "操作人 ID。"), - OperatorName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "操作人名称。"), - PreviousStatus = table.Column(type: "integer", nullable: true, comment: "原状态。"), - CurrentStatus = table.Column(type: "integer", nullable: true, comment: "新状态。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。") - }, - constraints: table => - { - table.PrimaryKey("PK_tenant_audit_logs", x => x.Id); - }, - comment: "租户运营审核日志。"); - - migrationBuilder.CreateTable( - name: "tenant_subscription_histories", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - TenantId = table.Column(type: "bigint", nullable: false, comment: "租户标识。"), - TenantSubscriptionId = table.Column(type: "bigint", nullable: false, comment: "对应的订阅 ID。"), - FromPackageId = table.Column(type: "bigint", nullable: false, comment: "原套餐 ID。"), - ToPackageId = table.Column(type: "bigint", nullable: false, comment: "新套餐 ID。"), - ChangeType = table.Column(type: "integer", nullable: false, comment: "变更类型。"), - EffectiveFrom = table.Column(type: "timestamp with time zone", nullable: false, comment: "生效时间。"), - EffectiveTo = table.Column(type: "timestamp with time zone", nullable: false, comment: "到期时间。"), - Amount = table.Column(type: "numeric", nullable: true, comment: "相关费用。"), - Currency = table.Column(type: "character varying(8)", maxLength: 8, nullable: true, comment: "币种。"), - Notes = table.Column(type: "character varying(512)", maxLength: 512, nullable: true, comment: "备注。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。") - }, - constraints: table => - { - table.PrimaryKey("PK_tenant_subscription_histories", x => x.Id); - }, - comment: "租户套餐订阅变更记录。"); - - migrationBuilder.CreateTable( - name: "tenant_verification_profiles", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - TenantId = table.Column(type: "bigint", nullable: false, comment: "对应的租户标识。"), - Status = table.Column(type: "integer", nullable: false, comment: "实名状态。"), - BusinessLicenseNumber = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "营业执照编号。"), - BusinessLicenseUrl = table.Column(type: "character varying(512)", maxLength: 512, nullable: true, comment: "营业执照文件地址。"), - LegalPersonName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "法人姓名。"), - LegalPersonIdNumber = table.Column(type: "character varying(32)", maxLength: 32, nullable: true, comment: "法人身份证号。"), - LegalPersonIdFrontUrl = table.Column(type: "character varying(512)", maxLength: 512, nullable: true, comment: "法人身份证正面。"), - LegalPersonIdBackUrl = table.Column(type: "character varying(512)", maxLength: 512, nullable: true, comment: "法人身份证反面。"), - BankAccountName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true, comment: "开户名。"), - BankAccountNumber = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "银行账号。"), - BankName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true, comment: "银行名称。"), - AdditionalDataJson = table.Column(type: "text", nullable: true, comment: "附加资料(JSON)。"), - SubmittedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "提交时间。"), - ReviewedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "审核时间。"), - ReviewedBy = table.Column(type: "bigint", nullable: true, comment: "审核人 ID。"), - ReviewedByName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "审核人姓名。"), - ReviewRemarks = table.Column(type: "character varying(512)", maxLength: 512, nullable: true, comment: "审核备注。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。") - }, - constraints: table => - { - table.PrimaryKey("PK_tenant_verification_profiles", x => x.Id); - }, - comment: "租户实名认证资料。"); - - migrationBuilder.CreateIndex( - name: "IX_inventory_lock_records_TenantId_IdempotencyKey", - table: "inventory_lock_records", - columns: new[] { "TenantId", "IdempotencyKey" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_inventory_lock_records_TenantId_StoreId_ProductSkuId_Status", - table: "inventory_lock_records", - columns: new[] { "TenantId", "StoreId", "ProductSkuId", "Status" }); - - migrationBuilder.CreateIndex( - name: "IX_merchant_audit_logs_TenantId_MerchantId", - table: "merchant_audit_logs", - columns: new[] { "TenantId", "MerchantId" }); - - migrationBuilder.CreateIndex( - name: "IX_merchant_categories_TenantId_Name", - table: "merchant_categories", - columns: new[] { "TenantId", "Name" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_store_pickup_settings_TenantId_StoreId", - table: "store_pickup_settings", - columns: new[] { "TenantId", "StoreId" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_store_pickup_slots_TenantId_StoreId_Name", - table: "store_pickup_slots", - columns: new[] { "TenantId", "StoreId", "Name" }); - - migrationBuilder.CreateIndex( - name: "IX_tenant_announcement_reads_TenantId_AnnouncementId_UserId", - table: "tenant_announcement_reads", - columns: new[] { "TenantId", "AnnouncementId", "UserId" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_tenant_announcements_TenantId_AnnouncementType_IsActive", - table: "tenant_announcements", - columns: new[] { "TenantId", "AnnouncementType", "IsActive" }); - - migrationBuilder.CreateIndex( - name: "IX_tenant_announcements_TenantId_EffectiveFrom_EffectiveTo", - table: "tenant_announcements", - columns: new[] { "TenantId", "EffectiveFrom", "EffectiveTo" }); - - migrationBuilder.CreateIndex( - name: "IX_tenant_audit_logs_TenantId", - table: "tenant_audit_logs", - column: "TenantId"); - - migrationBuilder.CreateIndex( - name: "IX_tenant_subscription_histories_TenantId_TenantSubscriptionId", - table: "tenant_subscription_histories", - columns: new[] { "TenantId", "TenantSubscriptionId" }); - - migrationBuilder.CreateIndex( - name: "IX_tenant_verification_profiles_TenantId", - table: "tenant_verification_profiles", - column: "TenantId", - unique: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "inventory_lock_records"); - - migrationBuilder.DropTable( - name: "merchant_audit_logs"); - - migrationBuilder.DropTable( - name: "merchant_categories"); - - migrationBuilder.DropTable( - name: "store_pickup_settings"); - - migrationBuilder.DropTable( - name: "store_pickup_slots"); - - migrationBuilder.DropTable( - name: "tenant_announcement_reads"); - - migrationBuilder.DropTable( - name: "tenant_announcements"); - - migrationBuilder.DropTable( - name: "tenant_audit_logs"); - - migrationBuilder.DropTable( - name: "tenant_subscription_histories"); - - migrationBuilder.DropTable( - name: "tenant_verification_profiles"); - - migrationBuilder.DropColumn( - name: "BatchConsumeStrategy", - table: "inventory_items"); - - migrationBuilder.DropColumn( - name: "IsPresale", - table: "inventory_items"); - - migrationBuilder.DropColumn( - name: "IsSoldOut", - table: "inventory_items"); - - migrationBuilder.DropColumn( - name: "MaxQuantityPerOrder", - table: "inventory_items"); - - migrationBuilder.DropColumn( - name: "PresaleCapacity", - table: "inventory_items"); - - migrationBuilder.DropColumn( - name: "PresaleEndTime", - table: "inventory_items"); - - migrationBuilder.DropColumn( - name: "PresaleLocked", - table: "inventory_items"); - - migrationBuilder.DropColumn( - name: "PresaleStartTime", - table: "inventory_items"); - - migrationBuilder.DropColumn( - name: "RowVersion", - table: "inventory_items"); - - migrationBuilder.DropColumn( - name: "RowVersion", - table: "inventory_batches"); - - migrationBuilder.AlterColumn( - name: "StoreId", - table: "queue_tickets", - type: "bigint", - nullable: false, - oldClrType: typeof(long), - oldType: "bigint", - oldComment: "获取或设置所属门店 ID。"); - - migrationBuilder.AlterColumn( - name: "OrderId", - table: "delivery_orders", - type: "bigint", - nullable: false, - oldClrType: typeof(long), - oldType: "bigint", - oldComment: "获取或设置关联订单 ID。"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251211150000_AddTenantPackageSortOrder.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251211150000_AddTenantPackageSortOrder.cs deleted file mode 100644 index 8233f91..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251211150000_AddTenantPackageSortOrder.cs +++ /dev/null @@ -1,50 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - /// - /// 为租户套餐新增排序字段与索引的迁移。 - /// - /// - public partial class AddTenantPackageSortOrder : Migration - { - /// - /// 升级:新增排序列并创建索引。 - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - // 1. 新增排序列,默认 0 - migrationBuilder.AddColumn( - name: "SortOrder", - table: "tenant_packages", - type: "integer", - nullable: false, - defaultValue: 0, - comment: "展示排序,数值越小越靠前。"); - - // 2. 创建可售+排序索引用于前台查询 - migrationBuilder.CreateIndex( - name: "IX_tenant_packages_IsActive_SortOrder", - table: "tenant_packages", - columns: new[] { "IsActive", "SortOrder" }); - } - - /// - /// 回滚:删除索引并移除排序列。 - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - // 1. 移除索引 - migrationBuilder.DropIndex( - name: "IX_tenant_packages_IsActive_SortOrder", - table: "tenant_packages"); - - // 2. 回滚排序列 - migrationBuilder.DropColumn( - name: "SortOrder", - table: "tenant_packages"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251212135400_AddTenantContactPhoneUniqueIndex.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251212135400_AddTenantContactPhoneUniqueIndex.Designer.cs deleted file mode 100644 index c4c5ccf..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251212135400_AddTenantContactPhoneUniqueIndex.Designer.cs +++ /dev/null @@ -1,6684 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.App.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - [DbContext(typeof(TakeoutAppDbContext))] - [Migration("20251212135400_AddTenantContactPhoneUniqueIndex")] - partial class AddTenantContactPhoneUniqueIndex - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricAlertRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionJson") - .IsRequired() - .HasColumnType("text") - .HasComment("触发条件 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Enabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("关联指标。"); - - b.Property("NotificationChannels") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("通知渠道。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("告警级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "Severity"); - - b.ToTable("metric_alert_rules", null, t => - { - t.HasComment("指标告警规则。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricDefinition", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("指标编码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultAggregation") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("默认聚合方式。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("说明。"); - - b.Property("DimensionsJson") - .HasColumnType("text") - .HasComment("维度描述 JSON。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("指标名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("metric_definitions", null, t => - { - t.HasComment("指标定义,描述可观测的数据点。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricSnapshot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DimensionKey") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("维度键(JSON)。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("指标定义 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Value") - .HasPrecision(18, 4) - .HasColumnType("numeric(18,4)") - .HasComment("数值。"); - - b.Property("WindowEnd") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口结束。"); - - b.Property("WindowStart") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口开始。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "DimensionKey", "WindowStart", "WindowEnd") - .IsUnique(); - - b.ToTable("metric_snapshots", null, t => - { - t.HasComment("指标快照,用于大盘展示。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.Coupon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("券码或序列号。"); - - b.Property("CouponTemplateId") - .HasColumnType("bigint") - .HasComment("模板标识。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("发放时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID(已使用时记录)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedAt") - .HasColumnType("timestamp with time zone") - .HasComment("使用时间。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("归属用户。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("coupons", null, t => - { - t.HasComment("用户领取的券。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.CouponTemplate", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowStack") - .HasColumnType("boolean") - .HasComment("是否允许叠加其他优惠。"); - - b.Property("ChannelsJson") - .HasColumnType("text") - .HasComment("发放渠道(JSON)。"); - - b.Property("ClaimedQuantity") - .HasColumnType("integer") - .HasComment("已领取数量。"); - - b.Property("CouponType") - .HasColumnType("integer") - .HasComment("券类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("DiscountCap") - .HasColumnType("numeric") - .HasComment("折扣上限(针对折扣券)。"); - - b.Property("MinimumSpend") - .HasColumnType("numeric") - .HasComment("最低消费门槛。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("模板名称。"); - - b.Property("ProductScopeJson") - .HasColumnType("text") - .HasComment("适用品类或商品范围(JSON)。"); - - b.Property("RelativeValidDays") - .HasColumnType("integer") - .HasComment("有效天数(相对发放时间)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreScopeJson") - .HasColumnType("text") - .HasComment("适用门店 ID 集合(JSON)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TotalQuantity") - .HasColumnType("integer") - .HasComment("总发放数量上限。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ValidFrom") - .HasColumnType("timestamp with time zone") - .HasComment("可用开始时间。"); - - b.Property("ValidTo") - .HasColumnType("timestamp with time zone") - .HasComment("可用结束时间。"); - - b.Property("Value") - .HasColumnType("numeric") - .HasComment("面值或折扣额度。"); - - b.HasKey("Id"); - - b.ToTable("coupon_templates", null, t => - { - t.HasComment("优惠券模板。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.PromotionCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AudienceDescription") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("目标人群描述。"); - - b.Property("BannerUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营销素材(如 banner)。"); - - b.Property("Budget") - .HasColumnType("numeric") - .HasComment("预算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("PromotionType") - .HasColumnType("integer") - .HasComment("活动类型。"); - - b.Property("RulesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("活动规则 JSON。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("活动状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("promotion_campaigns", null, t => - { - t.HasComment("营销活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChatSessionId") - .HasColumnType("bigint") - .HasComment("会话标识。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("消息内容。"); - - b.Property("ContentType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("消息类型(文字/图片/语音等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRead") - .HasColumnType("boolean") - .HasComment("是否已读。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("读取时间。"); - - b.Property("SenderType") - .HasColumnType("integer") - .HasComment("发送方类型。"); - - b.Property("SenderUserId") - .HasColumnType("bigint") - .HasComment("发送方用户 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ChatSessionId", "CreatedAt"); - - b.ToTable("chat_messages", null, t => - { - t.HasComment("会话消息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AgentUserId") - .HasColumnType("bigint") - .HasComment("当前客服员工 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("顾客用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndedAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("IsBotActive") - .HasColumnType("boolean") - .HasComment("是否机器人接待中。"); - - b.Property("SessionCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话编号。"); - - b.Property("StartedAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店(可空为平台)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionCode") - .IsUnique(); - - b.ToTable("chat_sessions", null, t => - { - t.HasComment("客服会话。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.SupportTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AssignedAgentId") - .HasColumnType("bigint") - .HasComment("指派的客服。"); - - b.Property("ClosedAt") - .HasColumnType("timestamp with time zone") - .HasComment("关闭时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("客户用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .IsRequired() - .HasColumnType("text") - .HasComment("工单详情。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单(如有)。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("优先级。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("Subject") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("工单主题。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("工单编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TicketNo") - .IsUnique(); - - b.ToTable("support_tickets", null, t => - { - t.HasComment("客服工单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.TicketComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttachmentsJson") - .HasColumnType("text") - .HasComment("附件 JSON。"); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人 ID。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsInternal") - .HasColumnType("boolean") - .HasComment("是否内部备注。"); - - b.Property("SupportTicketId") - .HasColumnType("bigint") - .HasComment("工单标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SupportTicketId"); - - b.ToTable("ticket_comments", null, t => - { - t.HasComment("工单评论/流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryEvent", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryOrderId") - .HasColumnType("bigint") - .HasComment("配送单标识。"); - - b.Property("EventType") - .HasColumnType("integer") - .HasComment("事件类型。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("事件描述。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始数据 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DeliveryOrderId", "EventType"); - - b.ToTable("delivery_events", null, t => - { - t.HasComment("配送状态事件流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CourierName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("骑手姓名。"); - - b.Property("CourierPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("骑手电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveredAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("DispatchedAt") - .HasColumnType("timestamp with time zone") - .HasComment("下发时间。"); - - b.Property("FailureReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("异常原因。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("获取或设置关联订单 ID。"); - - b.Property("PickedUpAt") - .HasColumnType("timestamp with time zone") - .HasComment("取餐时间。"); - - b.Property("Provider") - .HasColumnType("integer") - .HasComment("配送服务商。"); - - b.Property("ProviderOrderId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方配送单号。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId") - .IsUnique(); - - b.ToTable("delivery_orders", null, t => - { - t.HasComment("配送单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliateOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("推广人标识。"); - - b.Property("BuyerUserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedCommission") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("预计佣金。"); - - b.Property("OrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("订单金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("SettledAt") - .HasColumnType("timestamp with time zone") - .HasComment("结算完成时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "OrderId") - .IsUnique(); - - b.ToTable("affiliate_orders", null, t => - { - t.HasComment("分销订单记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePartner", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChannelType") - .HasColumnType("integer") - .HasComment("渠道类型。"); - - b.Property("CommissionRate") - .HasColumnType("numeric") - .HasComment("分成比例(0-1)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称或渠道名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID(如绑定平台账号)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DisplayName"); - - b.ToTable("affiliate_partners", null, t => - { - t.HasComment("分销/推广合作伙伴。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePayout", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("合作伙伴标识。"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("结算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("打款时间。"); - - b.Property("Period") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("结算周期描述。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "Period") - .IsUnique(); - - b.ToTable("affiliate_payouts", null, t => - { - t.HasComment("佣金结算记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowMakeupCount") - .HasColumnType("integer") - .HasComment("支持补签次数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("活动描述。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("结束日期。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("RewardsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("连签奖励 JSON。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("开始日期。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name"); - - b.ToTable("checkin_campaigns", null, t => - { - t.HasComment("签到活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CheckInCampaignId") - .HasColumnType("bigint") - .HasComment("活动标识。"); - - b.Property("CheckInDate") - .HasColumnType("timestamp with time zone") - .HasComment("签到日期(本地)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsMakeup") - .HasColumnType("boolean") - .HasComment("是否补签。"); - - b.Property("RewardJson") - .IsRequired() - .HasColumnType("text") - .HasComment("获得奖励 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "CheckInCampaignId", "UserId", "CheckInDate") - .IsUnique(); - - b.ToTable("checkin_records", null, t => - { - t.HasComment("用户签到记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsDeleted") - .HasColumnType("boolean") - .HasComment("状态。"); - - b.Property("ParentId") - .HasColumnType("bigint") - .HasComment("父级评论 ID。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "CreatedAt"); - - b.ToTable("community_comments", null, t => - { - t.HasComment("社区评论。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityPost", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("作者用户 ID。"); - - b.Property("CommentCount") - .HasColumnType("integer") - .HasComment("评论数。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LikeCount") - .HasColumnType("integer") - .HasComment("点赞数。"); - - b.Property("MediaJson") - .HasColumnType("text") - .HasComment("媒体资源 JSON。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AuthorUserId", "CreatedAt"); - - b.ToTable("community_posts", null, t => - { - t.HasComment("社区动态。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityReaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态 ID。"); - - b.Property("ReactedAt") - .HasColumnType("timestamp with time zone") - .HasComment("时间戳。"); - - b.Property("ReactionType") - .HasColumnType("integer") - .HasComment("反应类型。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "UserId") - .IsUnique(); - - b.ToTable("community_reactions", null, t => - { - t.HasComment("社区互动反馈。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentCount") - .HasColumnType("integer") - .HasComment("当前已参与人数。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("GroupOrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("拼单编号。"); - - b.Property("GroupPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("拼团价格。"); - - b.Property("LeaderUserId") - .HasColumnType("bigint") - .HasComment("团长用户 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("关联商品或套餐。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("拼团状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("SucceededAt") - .HasColumnType("timestamp with time zone") - .HasComment("成团时间。"); - - b.Property("TargetCount") - .HasColumnType("integer") - .HasComment("成团需要的人数。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderNo") - .IsUnique(); - - b.ToTable("group_orders", null, t => - { - t.HasComment("拼单活动。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupParticipant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GroupOrderId") - .HasColumnType("bigint") - .HasComment("拼单活动标识。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("参与时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("对应订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("参与状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderId", "UserId") - .IsUnique(); - - b.ToTable("group_participants", null, t => - { - t.HasComment("拼单参与者。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryAdjustment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdjustmentType") - .HasColumnType("integer") - .HasComment("调整类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("InventoryItemId") - .HasColumnType("bigint") - .HasComment("对应的库存记录标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("调整数量,正数增加,负数减少。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("原因说明。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "InventoryItemId", "OccurredAt"); - - b.ToTable("inventory_adjustments", null, t => - { - t.HasComment("库存调整记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryBatch", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("ProductionDate") - .HasColumnType("timestamp with time zone") - .HasComment("生产日期。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("入库数量。"); - - b.Property("RemainingQuantity") - .HasColumnType("integer") - .HasComment("剩余数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber") - .IsUnique(); - - b.ToTable("inventory_batches", null, t => - { - t.HasComment("SKU 批次信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchConsumeStrategy") - .HasColumnType("integer") - .HasComment("批次扣减策略。"); - - b.Property("BatchNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号,可为空表示混批。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售商品。"); - - b.Property("IsSoldOut") - .HasColumnType("boolean") - .HasComment("是否标记售罄。"); - - b.Property("Location") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("储位或仓位信息。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单品限购(覆盖商品级 MaxQuantityPerOrder)。"); - - b.Property("PresaleCapacity") - .HasColumnType("integer") - .HasComment("预售名额(上限)。"); - - b.Property("PresaleEndTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售结束时间(UTC)。"); - - b.Property("PresaleLocked") - .HasColumnType("integer") - .HasComment("当前预售已锁定数量。"); - - b.Property("PresaleStartTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售开始时间(UTC)。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("QuantityOnHand") - .HasColumnType("integer") - .HasComment("可用库存。"); - - b.Property("QuantityReserved") - .HasColumnType("integer") - .HasComment("已锁定库存(订单占用)。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("SafetyStock") - .HasColumnType("integer") - .HasComment("安全库存阈值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber"); - - b.ToTable("inventory_items", null, t => - { - t.HasComment("SKU 在门店的库存信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryLockRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("IdempotencyKey") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("幂等键。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售锁定。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU ID。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("锁定数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("锁定状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "IdempotencyKey") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "Status"); - - b.ToTable("inventory_lock_records", null, t => - { - t.HasComment("库存锁定记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberGrowthLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChangeValue") - .HasColumnType("integer") - .HasComment("变动数量。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentValue") - .HasColumnType("integer") - .HasComment("当前成长值。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_growth_logs", null, t => - { - t.HasComment("成长值变动日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberPointLedger", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BalanceAfterChange") - .HasColumnType("integer") - .HasComment("变动后余额。"); - - b.Property("ChangeAmount") - .HasColumnType("integer") - .HasComment("变动数量,可为负值。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(如适用)。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Reason") - .HasColumnType("integer") - .HasComment("变动原因。"); - - b.Property("SourceId") - .HasColumnType("bigint") - .HasComment("来源 ID(订单、活动等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_point_ledgers", null, t => - { - t.HasComment("积分变动流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AvatarUrl") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像。"); - - b.Property("BirthDate") - .HasColumnType("timestamp with time zone") - .HasComment("生日。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GrowthValue") - .HasColumnType("integer") - .HasComment("成长值/经验值。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("注册时间。"); - - b.Property("MemberTierId") - .HasColumnType("bigint") - .HasComment("当前会员等级 ID。"); - - b.Property("Mobile") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("Nickname") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称。"); - - b.Property("PointsBalance") - .HasColumnType("integer") - .HasComment("会员积分余额。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会员状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Mobile") - .IsUnique(); - - b.ToTable("member_profiles", null, t => - { - t.HasComment("会员档案。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberTier", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BenefitsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("等级权益(JSON)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("等级名称。"); - - b.Property("RequiredGrowth") - .HasColumnType("integer") - .HasComment("所需成长值。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("member_tiers", null, t => - { - t.HasComment("会员等级定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.Merchant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("BrandAlias") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("品牌简称或别名。"); - - b.Property("BrandName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("品牌名称(对外展示)。"); - - b.Property("BusinessLicenseImageUrl") - .HasColumnType("text") - .HasComment("营业执照扫描件地址。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照号。"); - - b.Property("Category") - .HasColumnType("text") - .HasComment("品牌所属品类,如火锅、咖啡等。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("联系邮箱。"); - - b.Property("ContactPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在区县。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("入驻时间。"); - - b.Property("LastReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次审核时间。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度信息。"); - - b.Property("LegalPerson") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人或负责人姓名。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("品牌 Logo。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度信息。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注或驳回原因。"); - - b.Property("ServicePhone") - .HasColumnType("text") - .HasComment("客服电话。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("入驻状态。"); - - b.Property("SupportEmail") - .HasColumnType("text") - .HasComment("客服邮箱。"); - - b.Property("TaxNumber") - .HasColumnType("text") - .HasComment("税号/统一社会信用代码。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.ToTable("merchants", null, t => - { - t.HasComment("商户主体信息,承载入驻和资质审核结果。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantAuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("动作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("详情描述。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("商户标识。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId"); - - b.ToTable("merchant_audit_logs", null, t => - { - t.HasComment("商户入驻审核日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("显示顺序,越小越靠前。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否可用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("类目名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("merchant_categories", null, t => - { - t.HasComment("商户可选类目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantContract", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ContractNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("合同编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同结束时间。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("合同文件存储地址。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("SignedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签署时间。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("合同状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TerminatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("终止时间。"); - - b.Property("TerminationReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("终止原因。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "ContractNumber") - .IsUnique(); - - b.ToTable("merchant_contracts", null, t => - { - t.HasComment("商户合同记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantDocument", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DocumentNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("证照编号。"); - - b.Property("DocumentType") - .HasColumnType("integer") - .HasComment("证照类型。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期日期。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("证照文件链接。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签发日期。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Remarks") - .HasColumnType("text") - .HasComment("审核备注或驳回原因。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("审核状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "DocumentType"); - - b.ToTable("merchant_documents", null, t => - { - t.HasComment("商户提交的资质或证照材料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantStaff", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Email") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("邮箱地址。"); - - b.Property("IdentityUserId") - .HasColumnType("bigint") - .HasComment("登录账号 ID(指向统一身份体系)。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("员工姓名。"); - - b.Property("PermissionsJson") - .HasColumnType("text") - .HasComment("自定义权限(JSON)。"); - - b.Property("Phone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("员工角色类型。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("员工状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("可选的关联门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "Phone"); - - b.ToTable("merchant_staff", null, t => - { - t.HasComment("商户员工账号,支持门店维度分配。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.MapLocation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Landmark") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("打车/导航落点描述。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("名称。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店 ID,可空表示独立 POI。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("map_locations", null, t => - { - t.HasComment("地图 POI 信息,用于门店定位和推荐。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.NavigationRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("来源通道(小程序、H5 等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("请求时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TargetApp") - .HasColumnType("integer") - .HasComment("跳转的地图应用。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId", "RequestedAt"); - - b.ToTable("navigation_requests", null, t => - { - t.HasComment("用户发起的导航请求日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("扩展 JSON(规格、加料选项等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品或 SKU 标识。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称快照。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("自定义备注(口味要求)。"); - - b.Property("ShoppingCartId") - .HasColumnType("bigint") - .HasComment("所属购物车标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价快照。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ShoppingCartId"); - - b.ToTable("cart_items", null, t => - { - t.HasComment("购物车条目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItemAddon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CartItemId") - .HasColumnType("bigint") - .HasComment("所属购物车条目。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("OptionId") - .HasColumnType("bigint") - .HasComment("选项 ID(可对应 ProductAddonOption)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("cart_item_addons", null, t => - { - t.HasComment("购物车条目的加料/附加项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CheckoutSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("SessionToken") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话 Token。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.Property("ValidationResultJson") - .IsRequired() - .HasColumnType("text") - .HasComment("校验结果明细 JSON。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionToken") - .IsUnique(); - - b.ToTable("checkout_sessions", null, t => - { - t.HasComment("结账会话,记录校验上下文。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.ShoppingCart", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryPreference") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("履约方式(堂食/自提/配送)缓存。"); - - b.Property("LastModifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次修改时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("购物车状态,包含正常/锁定。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableContext") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌码或场景标识(扫码点餐)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId") - .IsUnique(); - - b.ToTable("shopping_carts", null, t => - { - t.HasComment("用户购物车,按租户/门店隔离。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.Order", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("取消原因。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("下单渠道。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("顾客姓名。"); - - b.Property("CustomerPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("顾客手机号。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryType") - .HasColumnType("integer") - .HasComment("履约类型。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("优惠金额。"); - - b.Property("FinishedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("ItemsAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("商品总额。"); - - b.Property("OrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("订单号。"); - - b.Property("PaidAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付时间。"); - - b.Property("PayableAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额。"); - - b.Property("PaymentStatus") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("QueueNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队号(如有)。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationId") - .HasColumnType("bigint") - .HasComment("预约 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TableNo") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("就餐桌号。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "Status"); - - b.ToTable("orders", null, t => - { - t.HasComment("交易订单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("自定义属性 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("折扣金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品 ID。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("SkuName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("SKU/规格描述。"); - - b.Property("SubTotal") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("小计。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("单位。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("OrderId"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("order_items", null, t => - { - t.HasComment("订单明细。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderStatusHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注信息。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识(可为空表示系统)。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("变更后的状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId", "OccurredAt"); - - b.ToTable("order_status_histories", null, t => - { - t.HasComment("订单状态流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.RefundRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("申请金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("ProcessedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核完成时间。"); - - b.Property("Reason") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("申请原因。"); - - b.Property("RefundNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("退款单号。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("用户提交时间。"); - - b.Property("ReviewNotes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "RefundNo") - .IsUnique(); - - b.ToTable("refund_requests", null, t => - { - t.HasComment("售后/退款申请。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("支付金额。"); - - b.Property("ChannelTransactionId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方渠道单号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Method") - .HasColumnType("integer") - .HasComment("支付方式。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付完成时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始回调内容。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("错误/备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TradeNo") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("平台交易号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("payment_records", null, t => - { - t.HasComment("支付流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRefundRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("退款金额。"); - - b.Property("ChannelRefundId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("渠道退款流水号。"); - - b.Property("CompletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("渠道返回的原始数据 JSON。"); - - b.Property("PaymentRecordId") - .HasColumnType("bigint") - .HasComment("原支付记录标识。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("退款请求时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PaymentRecordId"); - - b.ToTable("payment_refund_records", null, t => - { - t.HasComment("支付渠道退款流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.Product", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CategoryId") - .HasColumnType("bigint") - .HasComment("所属分类。"); - - b.Property("CoverImage") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("主图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("商品描述。"); - - b.Property("EnableDelivery") - .HasColumnType("boolean") - .HasComment("支持配送。"); - - b.Property("EnableDineIn") - .HasColumnType("boolean") - .HasComment("支持堂食。"); - - b.Property("EnablePickup") - .HasColumnType("boolean") - .HasComment("支持自提。"); - - b.Property("GalleryImages") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Gallery 图片逗号分隔。"); - - b.Property("IsFeatured") - .HasColumnType("boolean") - .HasComment("是否热门推荐。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("最大每单限购。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("现价。"); - - b.Property("SpuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("商品编码。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("商品状态。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("库存数量(可选)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("Subtitle") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("副标题/卖点。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("售卖单位(份/杯等)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SpuCode") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("products", null, t => - { - t.HasComment("商品(SPU)信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("MaxSelect") - .HasColumnType("integer") - .HasComment("最大选择数量。"); - - b.Property("MinSelect") - .HasColumnType("integer") - .HasComment("最小选择数量。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "Name"); - - b.ToTable("product_addon_groups", null, t => - { - t.HasComment("加料/做法分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AddonGroupId") - .HasColumnType("bigint") - .HasComment("所属加料分组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选项。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("product_addon_options", null, t => - { - t.HasComment("加料选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称,例如“辣度”“份量”。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型(单选/多选)。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("显示排序。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店,可为空表示所有门店共享。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("product_attribute_groups", null, t => - { - t.HasComment("商品规格/属性分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributeGroupId") - .HasColumnType("bigint") - .HasComment("所属规格组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选中。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AttributeGroupId", "Name") - .IsUnique(); - - b.ToTable("product_attribute_options", null, t => - { - t.HasComment("商品规格选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("分类描述。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分类名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("product_categories", null, t => - { - t.HasComment("商品分类。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductMediaAsset", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Caption") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述或标题。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MediaType") - .HasColumnType("integer") - .HasComment("媒体类型。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品标识。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Url") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("媒资链接。"); - - b.HasKey("Id"); - - b.ToTable("product_media_assets", null, t => - { - t.HasComment("商品媒资素材。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductPricingRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("条件描述(JSON),如会员等级、渠道等。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效结束时间。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("特殊价格。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("RuleType") - .HasColumnType("integer") - .HasComment("策略类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StartTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效开始时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("WeekdaysJson") - .HasColumnType("text") - .HasComment("生效星期(JSON 数组)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "RuleType"); - - b.ToTable("product_pricing_rules", null, t => - { - t.HasComment("商品价格策略,支持会员价/时段价等。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductSku", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("规格属性 JSON(记录选项 ID)。"); - - b.Property("Barcode") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("条形码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("售价。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SkuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("SKU 编码。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("可售库存。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weight") - .HasPrecision(10, 3) - .HasColumnType("numeric(10,3)") - .HasComment("重量(千克)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SkuCode") - .IsUnique(); - - b.ToTable("product_skus", null, t => - { - t.HasComment("商品 SKU,记录具体规格组合价格。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Queues.Entities.QueueTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CalledAt") - .HasColumnType("timestamp with time zone") - .HasComment("叫号时间。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedWaitMinutes") - .HasColumnType("integer") - .HasComment("预计等待分钟。"); - - b.Property("ExpiredAt") - .HasColumnType("timestamp with time zone") - .HasComment("过号时间。"); - - b.Property("PartySize") - .HasColumnType("integer") - .HasComment("就餐人数。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("获取或设置所属门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNumber") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.HasIndex("TenantId", "StoreId", "TicketNumber") - .IsUnique(); - - b.ToTable("queue_tickets", null, t => - { - t.HasComment("排队叫号。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Reservations.Entities.Reservation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CheckInCode") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("核销码/到店码。"); - - b.Property("CheckedInAt") - .HasColumnType("timestamp with time zone") - .HasComment("实际签到时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("客户姓名。"); - - b.Property("CustomerPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PeopleCount") - .HasColumnType("integer") - .HasComment("用餐人数。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("预约号。"); - - b.Property("ReservationTime") - .HasColumnType("timestamp with time zone") - .HasComment("预约时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TablePreference") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌型/标签。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ReservationNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("reservations", null, t => - { - t.HasComment("预约/预订记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.Store", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("Announcement") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("门店公告。"); - - b.Property("BusinessHours") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("门店营业时段描述(备用字符串)。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("门店编码,便于扫码及外部对接。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家或地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("门店海报。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryRadiusKm") - .HasPrecision(6, 2) - .HasColumnType("numeric(6,2)") - .HasComment("默认配送半径(公里)。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("门店描述或公告。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区县信息。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("高德/腾讯地图经度。"); - - b.Property("ManagerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("门店负责人姓名。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("门店名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("门店当前运营状态。"); - - b.Property("SupportsDelivery") - .HasColumnType("boolean") - .HasComment("是否支持配送。"); - - b.Property("SupportsDineIn") - .HasColumnType("boolean") - .HasComment("是否支持堂食。"); - - b.Property("SupportsPickup") - .HasColumnType("boolean") - .HasComment("是否支持自提。"); - - b.Property("SupportsQueueing") - .HasColumnType("boolean") - .HasComment("支持排队叫号。"); - - b.Property("SupportsReservation") - .HasColumnType("boolean") - .HasComment("支持预约。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("门店标签(逗号分隔)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.HasIndex("TenantId", "MerchantId"); - - b.ToTable("stores", null, t => - { - t.HasComment("门店信息,承载营业配置与能力。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreBusinessHour", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CapacityLimit") - .HasColumnType("integer") - .HasComment("最大接待容量或单量限制。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DayOfWeek") - .HasColumnType("integer") - .HasComment("星期几,0 表示周日。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间(本地时间)。"); - - b.Property("HourType") - .HasColumnType("integer") - .HasComment("时段类型(正常营业、休息、预约等)。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间(本地时间)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "DayOfWeek"); - - b.ToTable("store_business_hours", null, t => - { - t.HasComment("门店营业时段配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreDeliveryZone", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("EstimatedMinutes") - .HasColumnType("integer") - .HasComment("预计送达分钟。"); - - b.Property("MinimumOrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("起送价。"); - - b.Property("PolygonGeoJson") - .IsRequired() - .HasColumnType("text") - .HasComment("GeoJSON 表示的多边形范围。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ZoneName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ZoneName"); - - b.ToTable("store_delivery_zones", null, t => - { - t.HasComment("门店配送范围配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreEmployeeShift", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("排班角色。"); - - b.Property("ShiftDate") - .HasColumnType("timestamp with time zone") - .HasComment("班次日期。"); - - b.Property("StaffId") - .HasColumnType("bigint") - .HasComment("员工标识。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ShiftDate", "StaffId") - .IsUnique(); - - b.ToTable("store_employee_shifts", null, t => - { - t.HasComment("门店员工排班记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreHoliday", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Date") - .HasColumnType("timestamp with time zone") - .HasComment("日期。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsClosed") - .HasColumnType("boolean") - .HasComment("是否全天闭店。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("说明内容。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Date") - .IsUnique(); - - b.ToTable("store_holidays", null, t => - { - t.HasComment("门店休息日或特殊营业日。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSetting", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowDaysAhead") - .HasColumnType("integer") - .HasComment("可预约天数(含当天)。"); - - b.Property("AllowToday") - .HasColumnType("boolean") - .HasComment("是否允许当天自提。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultCutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("默认截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单笔自提最大份数。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId") - .IsUnique(); - - b.ToTable("store_pickup_settings", null, t => - { - t.HasComment("门店自提配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSlot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("容量(份数)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("当天结束时间(UTC)。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("档期名称。"); - - b.Property("ReservedCount") - .HasColumnType("integer") - .HasComment("已占用数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("当天开始时间(UTC)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weekdays") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("适用星期(逗号分隔 1-7)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("store_pickup_slots", null, t => - { - t.HasComment("门店自提档期。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTable", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AreaId") - .HasColumnType("bigint") - .HasComment("所在区域 ID。"); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("可容纳人数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("QrCodeUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("桌码二维码地址。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前桌台状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("桌码。"); - - b.Property("Tags") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("桌台标签(堂食、快餐等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "TableCode") - .IsUnique(); - - b.ToTable("store_tables", null, t => - { - t.HasComment("桌台信息与二维码绑定。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTableArea", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("区域描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name") - .IsUnique(); - - b.ToTable("store_table_areas", null, t => - { - t.HasComment("门店桌台区域配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.Tenant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("text") - .HasComment("详细地址信息。"); - - b.Property("City") - .HasColumnType("text") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("租户短编码,作为跨系统引用的唯一标识。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("主联系人邮箱。"); - - b.Property("ContactName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("主联系人姓名。"); - - b.Property("ContactPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("主联系人电话。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家/地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("品牌海报或封面图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("服务生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("服务到期时间(UTC)。"); - - b.Property("Industry") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所属行业,如餐饮、零售等。"); - - b.Property("LegalEntityName") - .HasColumnType("text") - .HasComment("法人或公司主体名称。"); - - b.Property("LogoUrl") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("LOGO 图片地址。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("租户全称或品牌名称。"); - - b.Property("PrimaryOwnerUserId") - .HasColumnType("bigint") - .HasComment("系统内对应的租户所有者账号 ID。"); - - b.Property("Province") - .HasColumnType("text") - .HasComment("所在省份或州。"); - - b.Property("Remarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息,用于运营记录特殊说明。"); - - b.Property("ShortName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("对外展示的简称。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("租户当前状态,涵盖审核、启用、停用等场景。"); - - b.Property("SuspendedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次暂停服务时间。"); - - b.Property("SuspensionReason") - .HasColumnType("text") - .HasComment("暂停或终止的原因说明。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("业务标签集合(逗号分隔)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Website") - .HasColumnType("text") - .HasComment("官网或主要宣传链接。"); - - b.HasKey("Id"); - - b.HasIndex("Code") - .IsUnique(); - - b.HasIndex("ContactPhone") - .IsUnique(); - - b.ToTable("tenants", null, t => - { - t.HasComment("平台租户信息,描述租户的生命周期与基础资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementType") - .HasColumnType("integer") - .HasComment("公告类型。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("公告正文(可为 Markdown/HTML,前端自行渲染)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("失效时间(UTC),为空表示长期有效。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("展示优先级,数值越大越靠前。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("公告标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AnnouncementType", "IsActive"); - - b.HasIndex("TenantId", "EffectiveFrom", "EffectiveTo"); - - b.ToTable("tenant_announcements", null, t => - { - t.HasComment("租户公告。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncementRead", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementId") - .HasColumnType("bigint") - .HasComment("公告 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("已读时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("已读用户 ID(后台账号),为空表示租户级已读。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AnnouncementId", "UserId") - .IsUnique(); - - b.ToTable("tenant_announcement_reads", null, t => - { - t.HasComment("租户公告已读记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("操作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentStatus") - .HasColumnType("integer") - .HasComment("新状态。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("详细描述。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人名称。"); - - b.Property("PreviousStatus") - .HasColumnType("integer") - .HasComment("原状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("关联的租户标识。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("日志标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.ToTable("tenant_audit_logs", null, t => - { - t.HasComment("租户运营审核日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantBillingStatement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AmountDue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额。"); - - b.Property("AmountPaid") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DueDate") - .HasColumnType("timestamp with time zone") - .HasComment("到期日。"); - - b.Property("LineItemsJson") - .HasColumnType("text") - .HasComment("账单明细 JSON,记录各项费用。"); - - b.Property("PeriodEnd") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期结束时间。"); - - b.Property("PeriodStart") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期开始时间。"); - - b.Property("StatementNo") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("账单编号,供对账查询。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前付款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StatementNo") - .IsUnique(); - - b.ToTable("tenant_billing_statements", null, t => - { - t.HasComment("租户账单,用于呈现周期性收费。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantNotification", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("发布通道(站内、邮件、短信等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("通知正文。"); - - b.Property("MetadataJson") - .HasColumnType("text") - .HasComment("附加元数据 JSON。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("租户是否已阅读。"); - - b.Property("SentAt") - .HasColumnType("timestamp with time zone") - .HasComment("推送时间。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("通知重要级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("通知标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Channel", "SentAt"); - - b.ToTable("tenant_notifications", null, t => - { - t.HasComment("面向租户的站内通知或消息推送。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantPackage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("套餐描述,包含适用场景、权益等。"); - - b.Property("FeaturePoliciesJson") - .HasColumnType("text") - .HasComment("权益明细 JSON,记录自定义特性开关。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否仍可售卖。"); - - b.Property("MaxAccountCount") - .HasColumnType("integer") - .HasComment("允许创建的最大账号数。"); - - b.Property("MaxDeliveryOrders") - .HasColumnType("integer") - .HasComment("每月可调用的配送单数量上限。"); - - b.Property("MaxSmsCredits") - .HasColumnType("integer") - .HasComment("每月短信额度上限。"); - - b.Property("MaxStorageGb") - .HasColumnType("integer") - .HasComment("存储容量上限(GB)。"); - - b.Property("MaxStoreCount") - .HasColumnType("integer") - .HasComment("允许的最大门店数。"); - - b.Property("MonthlyPrice") - .HasColumnType("numeric") - .HasComment("月付价格,单位:人民币元。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("套餐名称,展示给租户的简称。"); - - b.Property("PackageType") - .HasColumnType("integer") - .HasComment("套餐分类(试用、标准、旗舰等)。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("展示排序,数值越小越靠前。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("YearlyPrice") - .HasColumnType("numeric") - .HasComment("年付价格,单位:人民币元。"); - - b.HasKey("Id"); - - b.HasIndex("IsActive", "SortOrder"); - - b.ToTable("tenant_packages", null, t => - { - t.HasComment("平台提供的租户套餐定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaUsage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LastResetAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次重置时间。"); - - b.Property("LimitValue") - .HasColumnType("numeric") - .HasComment("当前配额上限。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型,例如门店数、短信条数等。"); - - b.Property("ResetCycle") - .HasColumnType("text") - .HasComment("配额刷新周期描述(如月、年)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedValue") - .HasColumnType("numeric") - .HasComment("已消耗的数量。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "QuotaType") - .IsUnique(); - - b.ToTable("tenant_quota_usages", null, t => - { - t.HasComment("租户配额使用情况快照。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscription", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AutoRenew") - .HasColumnType("boolean") - .HasComment("是否开启自动续费。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("订阅生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("订阅到期时间(UTC)。"); - - b.Property("NextBillingDate") - .HasColumnType("timestamp with time zone") - .HasComment("下一个计费时间,配合自动续费使用。"); - - b.Property("Notes") - .HasColumnType("text") - .HasComment("运营备注信息。"); - - b.Property("ScheduledPackageId") - .HasColumnType("bigint") - .HasComment("若已排期升降配,对应的新套餐 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("订阅当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TenantPackageId") - .HasColumnType("bigint") - .HasComment("当前订阅关联的套餐标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantPackageId"); - - b.ToTable("tenant_subscriptions", null, t => - { - t.HasComment("租户套餐订阅记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscriptionHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasColumnType("numeric") - .HasComment("相关费用。"); - - b.Property("ChangeType") - .HasColumnType("integer") - .HasComment("变更类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Currency") - .HasMaxLength(8) - .HasColumnType("character varying(8)") - .HasComment("币种。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("FromPackageId") - .HasColumnType("bigint") - .HasComment("原套餐 ID。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("租户标识。"); - - b.Property("TenantSubscriptionId") - .HasColumnType("bigint") - .HasComment("对应的订阅 ID。"); - - b.Property("ToPackageId") - .HasColumnType("bigint") - .HasComment("新套餐 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantSubscriptionId"); - - b.ToTable("tenant_subscription_histories", null, t => - { - t.HasComment("租户套餐订阅变更记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantVerificationProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdditionalDataJson") - .HasColumnType("text") - .HasComment("附加资料(JSON)。"); - - b.Property("BankAccountName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("开户名。"); - - b.Property("BankAccountNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("银行账号。"); - - b.Property("BankName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("银行名称。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照编号。"); - - b.Property("BusinessLicenseUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营业执照文件地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LegalPersonIdBackUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证反面。"); - - b.Property("LegalPersonIdFrontUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证正面。"); - - b.Property("LegalPersonIdNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("法人身份证号。"); - - b.Property("LegalPersonName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人姓名。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注。"); - - b.Property("ReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核时间。"); - - b.Property("ReviewedBy") - .HasColumnType("bigint") - .HasComment("审核人 ID。"); - - b.Property("ReviewedByName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("审核人姓名。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("实名状态。"); - - b.Property("SubmittedAt") - .HasColumnType("timestamp with time zone") - .HasComment("提交时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("对应的租户标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId") - .IsUnique(); - - b.ToTable("tenant_verification_profiles", null, t => - { - t.HasComment("租户实名认证资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.HasOne("TakeoutSaaS.Domain.Orders.Entities.Order", null) - .WithMany() - .HasForeignKey("OrderId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251212135400_AddTenantContactPhoneUniqueIndex.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251212135400_AddTenantContactPhoneUniqueIndex.cs deleted file mode 100644 index 5e5f6ea..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251212135400_AddTenantContactPhoneUniqueIndex.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - /// - public partial class AddTenantContactPhoneUniqueIndex : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateIndex( - name: "IX_tenants_ContactPhone", - table: "tenants", - column: "ContactPhone", - unique: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_tenants_ContactPhone", - table: "tenants"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215023947_AddTenantReviewClaim.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215023947_AddTenantReviewClaim.Designer.cs deleted file mode 100644 index 81eba04..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215023947_AddTenantReviewClaim.Designer.cs +++ /dev/null @@ -1,6753 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.App.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - [DbContext(typeof(TakeoutAppDbContext))] - [Migration("20251215023947_AddTenantReviewClaim")] - partial class AddTenantReviewClaim - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricAlertRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionJson") - .IsRequired() - .HasColumnType("text") - .HasComment("触发条件 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Enabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("关联指标。"); - - b.Property("NotificationChannels") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("通知渠道。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("告警级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "Severity"); - - b.ToTable("metric_alert_rules", null, t => - { - t.HasComment("指标告警规则。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricDefinition", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("指标编码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultAggregation") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("默认聚合方式。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("说明。"); - - b.Property("DimensionsJson") - .HasColumnType("text") - .HasComment("维度描述 JSON。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("指标名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("metric_definitions", null, t => - { - t.HasComment("指标定义,描述可观测的数据点。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricSnapshot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DimensionKey") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("维度键(JSON)。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("指标定义 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Value") - .HasPrecision(18, 4) - .HasColumnType("numeric(18,4)") - .HasComment("数值。"); - - b.Property("WindowEnd") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口结束。"); - - b.Property("WindowStart") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口开始。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "DimensionKey", "WindowStart", "WindowEnd") - .IsUnique(); - - b.ToTable("metric_snapshots", null, t => - { - t.HasComment("指标快照,用于大盘展示。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.Coupon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("券码或序列号。"); - - b.Property("CouponTemplateId") - .HasColumnType("bigint") - .HasComment("模板标识。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("发放时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID(已使用时记录)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedAt") - .HasColumnType("timestamp with time zone") - .HasComment("使用时间。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("归属用户。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("coupons", null, t => - { - t.HasComment("用户领取的券。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.CouponTemplate", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowStack") - .HasColumnType("boolean") - .HasComment("是否允许叠加其他优惠。"); - - b.Property("ChannelsJson") - .HasColumnType("text") - .HasComment("发放渠道(JSON)。"); - - b.Property("ClaimedQuantity") - .HasColumnType("integer") - .HasComment("已领取数量。"); - - b.Property("CouponType") - .HasColumnType("integer") - .HasComment("券类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("DiscountCap") - .HasColumnType("numeric") - .HasComment("折扣上限(针对折扣券)。"); - - b.Property("MinimumSpend") - .HasColumnType("numeric") - .HasComment("最低消费门槛。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("模板名称。"); - - b.Property("ProductScopeJson") - .HasColumnType("text") - .HasComment("适用品类或商品范围(JSON)。"); - - b.Property("RelativeValidDays") - .HasColumnType("integer") - .HasComment("有效天数(相对发放时间)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreScopeJson") - .HasColumnType("text") - .HasComment("适用门店 ID 集合(JSON)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TotalQuantity") - .HasColumnType("integer") - .HasComment("总发放数量上限。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ValidFrom") - .HasColumnType("timestamp with time zone") - .HasComment("可用开始时间。"); - - b.Property("ValidTo") - .HasColumnType("timestamp with time zone") - .HasComment("可用结束时间。"); - - b.Property("Value") - .HasColumnType("numeric") - .HasComment("面值或折扣额度。"); - - b.HasKey("Id"); - - b.ToTable("coupon_templates", null, t => - { - t.HasComment("优惠券模板。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.PromotionCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AudienceDescription") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("目标人群描述。"); - - b.Property("BannerUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营销素材(如 banner)。"); - - b.Property("Budget") - .HasColumnType("numeric") - .HasComment("预算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("PromotionType") - .HasColumnType("integer") - .HasComment("活动类型。"); - - b.Property("RulesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("活动规则 JSON。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("活动状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("promotion_campaigns", null, t => - { - t.HasComment("营销活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChatSessionId") - .HasColumnType("bigint") - .HasComment("会话标识。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("消息内容。"); - - b.Property("ContentType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("消息类型(文字/图片/语音等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRead") - .HasColumnType("boolean") - .HasComment("是否已读。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("读取时间。"); - - b.Property("SenderType") - .HasColumnType("integer") - .HasComment("发送方类型。"); - - b.Property("SenderUserId") - .HasColumnType("bigint") - .HasComment("发送方用户 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ChatSessionId", "CreatedAt"); - - b.ToTable("chat_messages", null, t => - { - t.HasComment("会话消息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AgentUserId") - .HasColumnType("bigint") - .HasComment("当前客服员工 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("顾客用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndedAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("IsBotActive") - .HasColumnType("boolean") - .HasComment("是否机器人接待中。"); - - b.Property("SessionCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话编号。"); - - b.Property("StartedAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店(可空为平台)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionCode") - .IsUnique(); - - b.ToTable("chat_sessions", null, t => - { - t.HasComment("客服会话。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.SupportTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AssignedAgentId") - .HasColumnType("bigint") - .HasComment("指派的客服。"); - - b.Property("ClosedAt") - .HasColumnType("timestamp with time zone") - .HasComment("关闭时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("客户用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .IsRequired() - .HasColumnType("text") - .HasComment("工单详情。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单(如有)。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("优先级。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("Subject") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("工单主题。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("工单编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TicketNo") - .IsUnique(); - - b.ToTable("support_tickets", null, t => - { - t.HasComment("客服工单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.TicketComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttachmentsJson") - .HasColumnType("text") - .HasComment("附件 JSON。"); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人 ID。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsInternal") - .HasColumnType("boolean") - .HasComment("是否内部备注。"); - - b.Property("SupportTicketId") - .HasColumnType("bigint") - .HasComment("工单标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SupportTicketId"); - - b.ToTable("ticket_comments", null, t => - { - t.HasComment("工单评论/流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryEvent", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryOrderId") - .HasColumnType("bigint") - .HasComment("配送单标识。"); - - b.Property("EventType") - .HasColumnType("integer") - .HasComment("事件类型。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("事件描述。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始数据 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DeliveryOrderId", "EventType"); - - b.ToTable("delivery_events", null, t => - { - t.HasComment("配送状态事件流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CourierName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("骑手姓名。"); - - b.Property("CourierPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("骑手电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveredAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("DispatchedAt") - .HasColumnType("timestamp with time zone") - .HasComment("下发时间。"); - - b.Property("FailureReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("异常原因。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("获取或设置关联订单 ID。"); - - b.Property("PickedUpAt") - .HasColumnType("timestamp with time zone") - .HasComment("取餐时间。"); - - b.Property("Provider") - .HasColumnType("integer") - .HasComment("配送服务商。"); - - b.Property("ProviderOrderId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方配送单号。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId") - .IsUnique(); - - b.ToTable("delivery_orders", null, t => - { - t.HasComment("配送单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliateOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("推广人标识。"); - - b.Property("BuyerUserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedCommission") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("预计佣金。"); - - b.Property("OrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("订单金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("SettledAt") - .HasColumnType("timestamp with time zone") - .HasComment("结算完成时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "OrderId") - .IsUnique(); - - b.ToTable("affiliate_orders", null, t => - { - t.HasComment("分销订单记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePartner", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChannelType") - .HasColumnType("integer") - .HasComment("渠道类型。"); - - b.Property("CommissionRate") - .HasColumnType("numeric") - .HasComment("分成比例(0-1)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称或渠道名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID(如绑定平台账号)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DisplayName"); - - b.ToTable("affiliate_partners", null, t => - { - t.HasComment("分销/推广合作伙伴。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePayout", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("合作伙伴标识。"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("结算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("打款时间。"); - - b.Property("Period") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("结算周期描述。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "Period") - .IsUnique(); - - b.ToTable("affiliate_payouts", null, t => - { - t.HasComment("佣金结算记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowMakeupCount") - .HasColumnType("integer") - .HasComment("支持补签次数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("活动描述。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("结束日期。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("RewardsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("连签奖励 JSON。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("开始日期。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name"); - - b.ToTable("checkin_campaigns", null, t => - { - t.HasComment("签到活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CheckInCampaignId") - .HasColumnType("bigint") - .HasComment("活动标识。"); - - b.Property("CheckInDate") - .HasColumnType("timestamp with time zone") - .HasComment("签到日期(本地)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsMakeup") - .HasColumnType("boolean") - .HasComment("是否补签。"); - - b.Property("RewardJson") - .IsRequired() - .HasColumnType("text") - .HasComment("获得奖励 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "CheckInCampaignId", "UserId", "CheckInDate") - .IsUnique(); - - b.ToTable("checkin_records", null, t => - { - t.HasComment("用户签到记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsDeleted") - .HasColumnType("boolean") - .HasComment("状态。"); - - b.Property("ParentId") - .HasColumnType("bigint") - .HasComment("父级评论 ID。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "CreatedAt"); - - b.ToTable("community_comments", null, t => - { - t.HasComment("社区评论。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityPost", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("作者用户 ID。"); - - b.Property("CommentCount") - .HasColumnType("integer") - .HasComment("评论数。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LikeCount") - .HasColumnType("integer") - .HasComment("点赞数。"); - - b.Property("MediaJson") - .HasColumnType("text") - .HasComment("媒体资源 JSON。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AuthorUserId", "CreatedAt"); - - b.ToTable("community_posts", null, t => - { - t.HasComment("社区动态。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityReaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态 ID。"); - - b.Property("ReactedAt") - .HasColumnType("timestamp with time zone") - .HasComment("时间戳。"); - - b.Property("ReactionType") - .HasColumnType("integer") - .HasComment("反应类型。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "UserId") - .IsUnique(); - - b.ToTable("community_reactions", null, t => - { - t.HasComment("社区互动反馈。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentCount") - .HasColumnType("integer") - .HasComment("当前已参与人数。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("GroupOrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("拼单编号。"); - - b.Property("GroupPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("拼团价格。"); - - b.Property("LeaderUserId") - .HasColumnType("bigint") - .HasComment("团长用户 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("关联商品或套餐。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("拼团状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("SucceededAt") - .HasColumnType("timestamp with time zone") - .HasComment("成团时间。"); - - b.Property("TargetCount") - .HasColumnType("integer") - .HasComment("成团需要的人数。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderNo") - .IsUnique(); - - b.ToTable("group_orders", null, t => - { - t.HasComment("拼单活动。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupParticipant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GroupOrderId") - .HasColumnType("bigint") - .HasComment("拼单活动标识。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("参与时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("对应订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("参与状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderId", "UserId") - .IsUnique(); - - b.ToTable("group_participants", null, t => - { - t.HasComment("拼单参与者。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryAdjustment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdjustmentType") - .HasColumnType("integer") - .HasComment("调整类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("InventoryItemId") - .HasColumnType("bigint") - .HasComment("对应的库存记录标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("调整数量,正数增加,负数减少。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("原因说明。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "InventoryItemId", "OccurredAt"); - - b.ToTable("inventory_adjustments", null, t => - { - t.HasComment("库存调整记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryBatch", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("ProductionDate") - .HasColumnType("timestamp with time zone") - .HasComment("生产日期。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("入库数量。"); - - b.Property("RemainingQuantity") - .HasColumnType("integer") - .HasComment("剩余数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber") - .IsUnique(); - - b.ToTable("inventory_batches", null, t => - { - t.HasComment("SKU 批次信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchConsumeStrategy") - .HasColumnType("integer") - .HasComment("批次扣减策略。"); - - b.Property("BatchNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号,可为空表示混批。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售商品。"); - - b.Property("IsSoldOut") - .HasColumnType("boolean") - .HasComment("是否标记售罄。"); - - b.Property("Location") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("储位或仓位信息。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单品限购(覆盖商品级 MaxQuantityPerOrder)。"); - - b.Property("PresaleCapacity") - .HasColumnType("integer") - .HasComment("预售名额(上限)。"); - - b.Property("PresaleEndTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售结束时间(UTC)。"); - - b.Property("PresaleLocked") - .HasColumnType("integer") - .HasComment("当前预售已锁定数量。"); - - b.Property("PresaleStartTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售开始时间(UTC)。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("QuantityOnHand") - .HasColumnType("integer") - .HasComment("可用库存。"); - - b.Property("QuantityReserved") - .HasColumnType("integer") - .HasComment("已锁定库存(订单占用)。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("SafetyStock") - .HasColumnType("integer") - .HasComment("安全库存阈值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber"); - - b.ToTable("inventory_items", null, t => - { - t.HasComment("SKU 在门店的库存信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryLockRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("IdempotencyKey") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("幂等键。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售锁定。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU ID。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("锁定数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("锁定状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "IdempotencyKey") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "Status"); - - b.ToTable("inventory_lock_records", null, t => - { - t.HasComment("库存锁定记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberGrowthLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChangeValue") - .HasColumnType("integer") - .HasComment("变动数量。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentValue") - .HasColumnType("integer") - .HasComment("当前成长值。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_growth_logs", null, t => - { - t.HasComment("成长值变动日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberPointLedger", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BalanceAfterChange") - .HasColumnType("integer") - .HasComment("变动后余额。"); - - b.Property("ChangeAmount") - .HasColumnType("integer") - .HasComment("变动数量,可为负值。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(如适用)。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Reason") - .HasColumnType("integer") - .HasComment("变动原因。"); - - b.Property("SourceId") - .HasColumnType("bigint") - .HasComment("来源 ID(订单、活动等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_point_ledgers", null, t => - { - t.HasComment("积分变动流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AvatarUrl") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像。"); - - b.Property("BirthDate") - .HasColumnType("timestamp with time zone") - .HasComment("生日。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GrowthValue") - .HasColumnType("integer") - .HasComment("成长值/经验值。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("注册时间。"); - - b.Property("MemberTierId") - .HasColumnType("bigint") - .HasComment("当前会员等级 ID。"); - - b.Property("Mobile") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("Nickname") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称。"); - - b.Property("PointsBalance") - .HasColumnType("integer") - .HasComment("会员积分余额。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会员状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Mobile") - .IsUnique(); - - b.ToTable("member_profiles", null, t => - { - t.HasComment("会员档案。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberTier", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BenefitsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("等级权益(JSON)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("等级名称。"); - - b.Property("RequiredGrowth") - .HasColumnType("integer") - .HasComment("所需成长值。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("member_tiers", null, t => - { - t.HasComment("会员等级定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.Merchant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("BrandAlias") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("品牌简称或别名。"); - - b.Property("BrandName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("品牌名称(对外展示)。"); - - b.Property("BusinessLicenseImageUrl") - .HasColumnType("text") - .HasComment("营业执照扫描件地址。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照号。"); - - b.Property("Category") - .HasColumnType("text") - .HasComment("品牌所属品类,如火锅、咖啡等。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("联系邮箱。"); - - b.Property("ContactPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在区县。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("入驻时间。"); - - b.Property("LastReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次审核时间。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度信息。"); - - b.Property("LegalPerson") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人或负责人姓名。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("品牌 Logo。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度信息。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注或驳回原因。"); - - b.Property("ServicePhone") - .HasColumnType("text") - .HasComment("客服电话。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("入驻状态。"); - - b.Property("SupportEmail") - .HasColumnType("text") - .HasComment("客服邮箱。"); - - b.Property("TaxNumber") - .HasColumnType("text") - .HasComment("税号/统一社会信用代码。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.ToTable("merchants", null, t => - { - t.HasComment("商户主体信息,承载入驻和资质审核结果。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantAuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("动作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("详情描述。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("商户标识。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId"); - - b.ToTable("merchant_audit_logs", null, t => - { - t.HasComment("商户入驻审核日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("显示顺序,越小越靠前。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否可用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("类目名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("merchant_categories", null, t => - { - t.HasComment("商户可选类目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantContract", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ContractNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("合同编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同结束时间。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("合同文件存储地址。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("SignedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签署时间。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("合同状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TerminatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("终止时间。"); - - b.Property("TerminationReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("终止原因。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "ContractNumber") - .IsUnique(); - - b.ToTable("merchant_contracts", null, t => - { - t.HasComment("商户合同记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantDocument", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DocumentNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("证照编号。"); - - b.Property("DocumentType") - .HasColumnType("integer") - .HasComment("证照类型。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期日期。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("证照文件链接。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签发日期。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Remarks") - .HasColumnType("text") - .HasComment("审核备注或驳回原因。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("审核状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "DocumentType"); - - b.ToTable("merchant_documents", null, t => - { - t.HasComment("商户提交的资质或证照材料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantStaff", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Email") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("邮箱地址。"); - - b.Property("IdentityUserId") - .HasColumnType("bigint") - .HasComment("登录账号 ID(指向统一身份体系)。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("员工姓名。"); - - b.Property("PermissionsJson") - .HasColumnType("text") - .HasComment("自定义权限(JSON)。"); - - b.Property("Phone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("员工角色类型。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("员工状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("可选的关联门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "Phone"); - - b.ToTable("merchant_staff", null, t => - { - t.HasComment("商户员工账号,支持门店维度分配。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.MapLocation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Landmark") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("打车/导航落点描述。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("名称。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店 ID,可空表示独立 POI。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("map_locations", null, t => - { - t.HasComment("地图 POI 信息,用于门店定位和推荐。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.NavigationRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("来源通道(小程序、H5 等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("请求时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TargetApp") - .HasColumnType("integer") - .HasComment("跳转的地图应用。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId", "RequestedAt"); - - b.ToTable("navigation_requests", null, t => - { - t.HasComment("用户发起的导航请求日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("扩展 JSON(规格、加料选项等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品或 SKU 标识。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称快照。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("自定义备注(口味要求)。"); - - b.Property("ShoppingCartId") - .HasColumnType("bigint") - .HasComment("所属购物车标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价快照。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ShoppingCartId"); - - b.ToTable("cart_items", null, t => - { - t.HasComment("购物车条目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItemAddon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CartItemId") - .HasColumnType("bigint") - .HasComment("所属购物车条目。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("OptionId") - .HasColumnType("bigint") - .HasComment("选项 ID(可对应 ProductAddonOption)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("cart_item_addons", null, t => - { - t.HasComment("购物车条目的加料/附加项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CheckoutSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("SessionToken") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话 Token。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.Property("ValidationResultJson") - .IsRequired() - .HasColumnType("text") - .HasComment("校验结果明细 JSON。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionToken") - .IsUnique(); - - b.ToTable("checkout_sessions", null, t => - { - t.HasComment("结账会话,记录校验上下文。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.ShoppingCart", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryPreference") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("履约方式(堂食/自提/配送)缓存。"); - - b.Property("LastModifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次修改时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("购物车状态,包含正常/锁定。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableContext") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌码或场景标识(扫码点餐)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId") - .IsUnique(); - - b.ToTable("shopping_carts", null, t => - { - t.HasComment("用户购物车,按租户/门店隔离。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.Order", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("取消原因。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("下单渠道。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("顾客姓名。"); - - b.Property("CustomerPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("顾客手机号。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryType") - .HasColumnType("integer") - .HasComment("履约类型。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("优惠金额。"); - - b.Property("FinishedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("ItemsAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("商品总额。"); - - b.Property("OrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("订单号。"); - - b.Property("PaidAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付时间。"); - - b.Property("PayableAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额。"); - - b.Property("PaymentStatus") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("QueueNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队号(如有)。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationId") - .HasColumnType("bigint") - .HasComment("预约 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TableNo") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("就餐桌号。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "Status"); - - b.ToTable("orders", null, t => - { - t.HasComment("交易订单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("自定义属性 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("折扣金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品 ID。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("SkuName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("SKU/规格描述。"); - - b.Property("SubTotal") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("小计。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("单位。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("OrderId"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("order_items", null, t => - { - t.HasComment("订单明细。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderStatusHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注信息。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识(可为空表示系统)。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("变更后的状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId", "OccurredAt"); - - b.ToTable("order_status_histories", null, t => - { - t.HasComment("订单状态流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.RefundRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("申请金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("ProcessedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核完成时间。"); - - b.Property("Reason") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("申请原因。"); - - b.Property("RefundNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("退款单号。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("用户提交时间。"); - - b.Property("ReviewNotes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "RefundNo") - .IsUnique(); - - b.ToTable("refund_requests", null, t => - { - t.HasComment("售后/退款申请。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("支付金额。"); - - b.Property("ChannelTransactionId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方渠道单号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Method") - .HasColumnType("integer") - .HasComment("支付方式。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付完成时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始回调内容。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("错误/备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TradeNo") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("平台交易号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("payment_records", null, t => - { - t.HasComment("支付流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRefundRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("退款金额。"); - - b.Property("ChannelRefundId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("渠道退款流水号。"); - - b.Property("CompletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("渠道返回的原始数据 JSON。"); - - b.Property("PaymentRecordId") - .HasColumnType("bigint") - .HasComment("原支付记录标识。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("退款请求时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PaymentRecordId"); - - b.ToTable("payment_refund_records", null, t => - { - t.HasComment("支付渠道退款流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.Product", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CategoryId") - .HasColumnType("bigint") - .HasComment("所属分类。"); - - b.Property("CoverImage") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("主图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("商品描述。"); - - b.Property("EnableDelivery") - .HasColumnType("boolean") - .HasComment("支持配送。"); - - b.Property("EnableDineIn") - .HasColumnType("boolean") - .HasComment("支持堂食。"); - - b.Property("EnablePickup") - .HasColumnType("boolean") - .HasComment("支持自提。"); - - b.Property("GalleryImages") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Gallery 图片逗号分隔。"); - - b.Property("IsFeatured") - .HasColumnType("boolean") - .HasComment("是否热门推荐。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("最大每单限购。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("现价。"); - - b.Property("SpuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("商品编码。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("商品状态。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("库存数量(可选)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("Subtitle") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("副标题/卖点。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("售卖单位(份/杯等)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SpuCode") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("products", null, t => - { - t.HasComment("商品(SPU)信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("MaxSelect") - .HasColumnType("integer") - .HasComment("最大选择数量。"); - - b.Property("MinSelect") - .HasColumnType("integer") - .HasComment("最小选择数量。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "Name"); - - b.ToTable("product_addon_groups", null, t => - { - t.HasComment("加料/做法分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AddonGroupId") - .HasColumnType("bigint") - .HasComment("所属加料分组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选项。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("product_addon_options", null, t => - { - t.HasComment("加料选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称,例如“辣度”“份量”。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型(单选/多选)。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("显示排序。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店,可为空表示所有门店共享。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("product_attribute_groups", null, t => - { - t.HasComment("商品规格/属性分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributeGroupId") - .HasColumnType("bigint") - .HasComment("所属规格组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选中。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AttributeGroupId", "Name") - .IsUnique(); - - b.ToTable("product_attribute_options", null, t => - { - t.HasComment("商品规格选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("分类描述。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分类名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("product_categories", null, t => - { - t.HasComment("商品分类。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductMediaAsset", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Caption") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述或标题。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MediaType") - .HasColumnType("integer") - .HasComment("媒体类型。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品标识。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Url") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("媒资链接。"); - - b.HasKey("Id"); - - b.ToTable("product_media_assets", null, t => - { - t.HasComment("商品媒资素材。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductPricingRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("条件描述(JSON),如会员等级、渠道等。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效结束时间。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("特殊价格。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("RuleType") - .HasColumnType("integer") - .HasComment("策略类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StartTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效开始时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("WeekdaysJson") - .HasColumnType("text") - .HasComment("生效星期(JSON 数组)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "RuleType"); - - b.ToTable("product_pricing_rules", null, t => - { - t.HasComment("商品价格策略,支持会员价/时段价等。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductSku", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("规格属性 JSON(记录选项 ID)。"); - - b.Property("Barcode") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("条形码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("售价。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SkuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("SKU 编码。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("可售库存。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weight") - .HasPrecision(10, 3) - .HasColumnType("numeric(10,3)") - .HasComment("重量(千克)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SkuCode") - .IsUnique(); - - b.ToTable("product_skus", null, t => - { - t.HasComment("商品 SKU,记录具体规格组合价格。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Queues.Entities.QueueTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CalledAt") - .HasColumnType("timestamp with time zone") - .HasComment("叫号时间。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedWaitMinutes") - .HasColumnType("integer") - .HasComment("预计等待分钟。"); - - b.Property("ExpiredAt") - .HasColumnType("timestamp with time zone") - .HasComment("过号时间。"); - - b.Property("PartySize") - .HasColumnType("integer") - .HasComment("就餐人数。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("获取或设置所属门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNumber") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.HasIndex("TenantId", "StoreId", "TicketNumber") - .IsUnique(); - - b.ToTable("queue_tickets", null, t => - { - t.HasComment("排队叫号。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Reservations.Entities.Reservation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CheckInCode") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("核销码/到店码。"); - - b.Property("CheckedInAt") - .HasColumnType("timestamp with time zone") - .HasComment("实际签到时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("客户姓名。"); - - b.Property("CustomerPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PeopleCount") - .HasColumnType("integer") - .HasComment("用餐人数。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("预约号。"); - - b.Property("ReservationTime") - .HasColumnType("timestamp with time zone") - .HasComment("预约时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TablePreference") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌型/标签。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ReservationNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("reservations", null, t => - { - t.HasComment("预约/预订记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.Store", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("Announcement") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("门店公告。"); - - b.Property("BusinessHours") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("门店营业时段描述(备用字符串)。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("门店编码,便于扫码及外部对接。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家或地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("门店海报。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryRadiusKm") - .HasPrecision(6, 2) - .HasColumnType("numeric(6,2)") - .HasComment("默认配送半径(公里)。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("门店描述或公告。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区县信息。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("高德/腾讯地图经度。"); - - b.Property("ManagerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("门店负责人姓名。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("门店名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("门店当前运营状态。"); - - b.Property("SupportsDelivery") - .HasColumnType("boolean") - .HasComment("是否支持配送。"); - - b.Property("SupportsDineIn") - .HasColumnType("boolean") - .HasComment("是否支持堂食。"); - - b.Property("SupportsPickup") - .HasColumnType("boolean") - .HasComment("是否支持自提。"); - - b.Property("SupportsQueueing") - .HasColumnType("boolean") - .HasComment("支持排队叫号。"); - - b.Property("SupportsReservation") - .HasColumnType("boolean") - .HasComment("支持预约。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("门店标签(逗号分隔)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.HasIndex("TenantId", "MerchantId"); - - b.ToTable("stores", null, t => - { - t.HasComment("门店信息,承载营业配置与能力。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreBusinessHour", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CapacityLimit") - .HasColumnType("integer") - .HasComment("最大接待容量或单量限制。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DayOfWeek") - .HasColumnType("integer") - .HasComment("星期几,0 表示周日。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间(本地时间)。"); - - b.Property("HourType") - .HasColumnType("integer") - .HasComment("时段类型(正常营业、休息、预约等)。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间(本地时间)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "DayOfWeek"); - - b.ToTable("store_business_hours", null, t => - { - t.HasComment("门店营业时段配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreDeliveryZone", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("EstimatedMinutes") - .HasColumnType("integer") - .HasComment("预计送达分钟。"); - - b.Property("MinimumOrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("起送价。"); - - b.Property("PolygonGeoJson") - .IsRequired() - .HasColumnType("text") - .HasComment("GeoJSON 表示的多边形范围。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ZoneName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ZoneName"); - - b.ToTable("store_delivery_zones", null, t => - { - t.HasComment("门店配送范围配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreEmployeeShift", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("排班角色。"); - - b.Property("ShiftDate") - .HasColumnType("timestamp with time zone") - .HasComment("班次日期。"); - - b.Property("StaffId") - .HasColumnType("bigint") - .HasComment("员工标识。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ShiftDate", "StaffId") - .IsUnique(); - - b.ToTable("store_employee_shifts", null, t => - { - t.HasComment("门店员工排班记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreHoliday", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Date") - .HasColumnType("timestamp with time zone") - .HasComment("日期。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsClosed") - .HasColumnType("boolean") - .HasComment("是否全天闭店。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("说明内容。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Date") - .IsUnique(); - - b.ToTable("store_holidays", null, t => - { - t.HasComment("门店休息日或特殊营业日。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSetting", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowDaysAhead") - .HasColumnType("integer") - .HasComment("可预约天数(含当天)。"); - - b.Property("AllowToday") - .HasColumnType("boolean") - .HasComment("是否允许当天自提。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultCutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("默认截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单笔自提最大份数。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId") - .IsUnique(); - - b.ToTable("store_pickup_settings", null, t => - { - t.HasComment("门店自提配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSlot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("容量(份数)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("当天结束时间(UTC)。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("档期名称。"); - - b.Property("ReservedCount") - .HasColumnType("integer") - .HasComment("已占用数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("当天开始时间(UTC)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weekdays") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("适用星期(逗号分隔 1-7)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("store_pickup_slots", null, t => - { - t.HasComment("门店自提档期。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTable", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AreaId") - .HasColumnType("bigint") - .HasComment("所在区域 ID。"); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("可容纳人数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("QrCodeUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("桌码二维码地址。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前桌台状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("桌码。"); - - b.Property("Tags") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("桌台标签(堂食、快餐等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "TableCode") - .IsUnique(); - - b.ToTable("store_tables", null, t => - { - t.HasComment("桌台信息与二维码绑定。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTableArea", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("区域描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name") - .IsUnique(); - - b.ToTable("store_table_areas", null, t => - { - t.HasComment("门店桌台区域配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.Tenant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("text") - .HasComment("详细地址信息。"); - - b.Property("City") - .HasColumnType("text") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("租户短编码,作为跨系统引用的唯一标识。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("主联系人邮箱。"); - - b.Property("ContactName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("主联系人姓名。"); - - b.Property("ContactPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("主联系人电话。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家/地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("品牌海报或封面图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("服务生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("服务到期时间(UTC)。"); - - b.Property("Industry") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所属行业,如餐饮、零售等。"); - - b.Property("LegalEntityName") - .HasColumnType("text") - .HasComment("法人或公司主体名称。"); - - b.Property("LogoUrl") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("LOGO 图片地址。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("租户全称或品牌名称。"); - - b.Property("PrimaryOwnerUserId") - .HasColumnType("bigint") - .HasComment("系统内对应的租户所有者账号 ID。"); - - b.Property("Province") - .HasColumnType("text") - .HasComment("所在省份或州。"); - - b.Property("Remarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息,用于运营记录特殊说明。"); - - b.Property("ShortName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("对外展示的简称。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("租户当前状态,涵盖审核、启用、停用等场景。"); - - b.Property("SuspendedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次暂停服务时间。"); - - b.Property("SuspensionReason") - .HasColumnType("text") - .HasComment("暂停或终止的原因说明。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("业务标签集合(逗号分隔)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Website") - .HasColumnType("text") - .HasComment("官网或主要宣传链接。"); - - b.HasKey("Id"); - - b.HasIndex("Code") - .IsUnique(); - - b.HasIndex("ContactPhone") - .IsUnique(); - - b.ToTable("tenants", null, t => - { - t.HasComment("平台租户信息,描述租户的生命周期与基础资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementType") - .HasColumnType("integer") - .HasComment("公告类型。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("公告正文(可为 Markdown/HTML,前端自行渲染)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("失效时间(UTC),为空表示长期有效。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("展示优先级,数值越大越靠前。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("公告标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AnnouncementType", "IsActive"); - - b.HasIndex("TenantId", "EffectiveFrom", "EffectiveTo"); - - b.ToTable("tenant_announcements", null, t => - { - t.HasComment("租户公告。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncementRead", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementId") - .HasColumnType("bigint") - .HasComment("公告 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("已读时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("已读用户 ID(后台账号),为空表示租户级已读。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AnnouncementId", "UserId") - .IsUnique(); - - b.ToTable("tenant_announcement_reads", null, t => - { - t.HasComment("租户公告已读记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("操作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentStatus") - .HasColumnType("integer") - .HasComment("新状态。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("详细描述。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人名称。"); - - b.Property("PreviousStatus") - .HasColumnType("integer") - .HasComment("原状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("关联的租户标识。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("日志标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.ToTable("tenant_audit_logs", null, t => - { - t.HasComment("租户运营审核日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantBillingStatement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AmountDue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额。"); - - b.Property("AmountPaid") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DueDate") - .HasColumnType("timestamp with time zone") - .HasComment("到期日。"); - - b.Property("LineItemsJson") - .HasColumnType("text") - .HasComment("账单明细 JSON,记录各项费用。"); - - b.Property("PeriodEnd") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期结束时间。"); - - b.Property("PeriodStart") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期开始时间。"); - - b.Property("StatementNo") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("账单编号,供对账查询。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前付款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StatementNo") - .IsUnique(); - - b.ToTable("tenant_billing_statements", null, t => - { - t.HasComment("租户账单,用于呈现周期性收费。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantNotification", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("发布通道(站内、邮件、短信等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("通知正文。"); - - b.Property("MetadataJson") - .HasColumnType("text") - .HasComment("附加元数据 JSON。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("租户是否已阅读。"); - - b.Property("SentAt") - .HasColumnType("timestamp with time zone") - .HasComment("推送时间。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("通知重要级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("通知标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Channel", "SentAt"); - - b.ToTable("tenant_notifications", null, t => - { - t.HasComment("面向租户的站内通知或消息推送。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantPackage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("套餐描述,包含适用场景、权益等。"); - - b.Property("FeaturePoliciesJson") - .HasColumnType("text") - .HasComment("权益明细 JSON,记录自定义特性开关。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否仍可售卖。"); - - b.Property("MaxAccountCount") - .HasColumnType("integer") - .HasComment("允许创建的最大账号数。"); - - b.Property("MaxDeliveryOrders") - .HasColumnType("integer") - .HasComment("每月可调用的配送单数量上限。"); - - b.Property("MaxSmsCredits") - .HasColumnType("integer") - .HasComment("每月短信额度上限。"); - - b.Property("MaxStorageGb") - .HasColumnType("integer") - .HasComment("存储容量上限(GB)。"); - - b.Property("MaxStoreCount") - .HasColumnType("integer") - .HasComment("允许的最大门店数。"); - - b.Property("MonthlyPrice") - .HasColumnType("numeric") - .HasComment("月付价格,单位:人民币元。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("套餐名称,展示给租户的简称。"); - - b.Property("PackageType") - .HasColumnType("integer") - .HasComment("套餐分类(试用、标准、旗舰等)。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("展示排序,数值越小越靠前。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("YearlyPrice") - .HasColumnType("numeric") - .HasComment("年付价格,单位:人民币元。"); - - b.HasKey("Id"); - - b.HasIndex("IsActive", "SortOrder"); - - b.ToTable("tenant_packages", null, t => - { - t.HasComment("平台提供的租户套餐定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaUsage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LastResetAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次重置时间。"); - - b.Property("LimitValue") - .HasColumnType("numeric") - .HasComment("当前配额上限。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型,例如门店数、短信条数等。"); - - b.Property("ResetCycle") - .HasColumnType("text") - .HasComment("配额刷新周期描述(如月、年)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedValue") - .HasColumnType("numeric") - .HasComment("已消耗的数量。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "QuotaType") - .IsUnique(); - - b.ToTable("tenant_quota_usages", null, t => - { - t.HasComment("租户配额使用情况快照。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantReviewClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ClaimedAt") - .HasColumnType("timestamp with time zone") - .HasComment("领取时间(UTC)。"); - - b.Property("ClaimedBy") - .HasColumnType("bigint") - .HasComment("领取人用户 ID。"); - - b.Property("ClaimedByName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("领取人名称(展示用快照)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReleasedAt") - .HasColumnType("timestamp with time zone") - .HasComment("释放时间(UTC),未释放时为 null。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("被领取的租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("ClaimedBy"); - - b.HasIndex("TenantId") - .IsUnique() - .HasFilter("\"ReleasedAt\" IS NULL AND \"DeletedAt\" IS NULL"); - - b.ToTable("tenant_review_claims", null, t => - { - t.HasComment("租户入驻审核领取记录(防止多管理员并发审核)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscription", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AutoRenew") - .HasColumnType("boolean") - .HasComment("是否开启自动续费。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("订阅生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("订阅到期时间(UTC)。"); - - b.Property("NextBillingDate") - .HasColumnType("timestamp with time zone") - .HasComment("下一个计费时间,配合自动续费使用。"); - - b.Property("Notes") - .HasColumnType("text") - .HasComment("运营备注信息。"); - - b.Property("ScheduledPackageId") - .HasColumnType("bigint") - .HasComment("若已排期升降配,对应的新套餐 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("订阅当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TenantPackageId") - .HasColumnType("bigint") - .HasComment("当前订阅关联的套餐标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantPackageId"); - - b.ToTable("tenant_subscriptions", null, t => - { - t.HasComment("租户套餐订阅记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscriptionHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasColumnType("numeric") - .HasComment("相关费用。"); - - b.Property("ChangeType") - .HasColumnType("integer") - .HasComment("变更类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Currency") - .HasMaxLength(8) - .HasColumnType("character varying(8)") - .HasComment("币种。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("FromPackageId") - .HasColumnType("bigint") - .HasComment("原套餐 ID。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("租户标识。"); - - b.Property("TenantSubscriptionId") - .HasColumnType("bigint") - .HasComment("对应的订阅 ID。"); - - b.Property("ToPackageId") - .HasColumnType("bigint") - .HasComment("新套餐 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantSubscriptionId"); - - b.ToTable("tenant_subscription_histories", null, t => - { - t.HasComment("租户套餐订阅变更记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantVerificationProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdditionalDataJson") - .HasColumnType("text") - .HasComment("附加资料(JSON)。"); - - b.Property("BankAccountName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("开户名。"); - - b.Property("BankAccountNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("银行账号。"); - - b.Property("BankName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("银行名称。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照编号。"); - - b.Property("BusinessLicenseUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营业执照文件地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LegalPersonIdBackUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证反面。"); - - b.Property("LegalPersonIdFrontUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证正面。"); - - b.Property("LegalPersonIdNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("法人身份证号。"); - - b.Property("LegalPersonName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人姓名。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注。"); - - b.Property("ReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核时间。"); - - b.Property("ReviewedBy") - .HasColumnType("bigint") - .HasComment("审核人 ID。"); - - b.Property("ReviewedByName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("审核人姓名。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("实名状态。"); - - b.Property("SubmittedAt") - .HasColumnType("timestamp with time zone") - .HasComment("提交时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("对应的租户标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId") - .IsUnique(); - - b.ToTable("tenant_verification_profiles", null, t => - { - t.HasComment("租户实名认证资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.HasOne("TakeoutSaaS.Domain.Orders.Entities.Order", null) - .WithMany() - .HasForeignKey("OrderId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215023947_AddTenantReviewClaim.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215023947_AddTenantReviewClaim.cs deleted file mode 100644 index 079bbe7..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215023947_AddTenantReviewClaim.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - /// - public partial class AddTenantReviewClaim : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "tenant_review_claims", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - TenantId = table.Column(type: "bigint", nullable: false, comment: "被领取的租户 ID。"), - ClaimedBy = table.Column(type: "bigint", nullable: false, comment: "领取人用户 ID。"), - ClaimedByName = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "领取人名称(展示用快照)。"), - ClaimedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "领取时间(UTC)。"), - ReleasedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "释放时间(UTC),未释放时为 null。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。") - }, - constraints: table => - { - table.PrimaryKey("PK_tenant_review_claims", x => x.Id); - }, - comment: "租户入驻审核领取记录(防止多管理员并发审核)。"); - - migrationBuilder.CreateIndex( - name: "IX_tenant_review_claims_ClaimedBy", - table: "tenant_review_claims", - column: "ClaimedBy"); - - migrationBuilder.CreateIndex( - name: "IX_tenant_review_claims_TenantId", - table: "tenant_review_claims", - column: "TenantId", - unique: true, - filter: "\"ReleasedAt\" IS NULL AND \"DeletedAt\" IS NULL"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "tenant_review_claims"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215092810_AddTenantPackagePublishAndVisibility.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215092810_AddTenantPackagePublishAndVisibility.Designer.cs deleted file mode 100644 index eedb01b..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215092810_AddTenantPackagePublishAndVisibility.Designer.cs +++ /dev/null @@ -1,6772 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.App.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - [DbContext(typeof(TakeoutAppDbContext))] - [Migration("20251215092810_AddTenantPackagePublishAndVisibility")] - partial class AddTenantPackagePublishAndVisibility - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricAlertRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionJson") - .IsRequired() - .HasColumnType("text") - .HasComment("触发条件 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Enabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("关联指标。"); - - b.Property("NotificationChannels") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("通知渠道。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("告警级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "Severity"); - - b.ToTable("metric_alert_rules", null, t => - { - t.HasComment("指标告警规则。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricDefinition", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("指标编码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultAggregation") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("默认聚合方式。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("说明。"); - - b.Property("DimensionsJson") - .HasColumnType("text") - .HasComment("维度描述 JSON。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("指标名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("metric_definitions", null, t => - { - t.HasComment("指标定义,描述可观测的数据点。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricSnapshot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DimensionKey") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("维度键(JSON)。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("指标定义 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Value") - .HasPrecision(18, 4) - .HasColumnType("numeric(18,4)") - .HasComment("数值。"); - - b.Property("WindowEnd") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口结束。"); - - b.Property("WindowStart") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口开始。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "DimensionKey", "WindowStart", "WindowEnd") - .IsUnique(); - - b.ToTable("metric_snapshots", null, t => - { - t.HasComment("指标快照,用于大盘展示。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.Coupon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("券码或序列号。"); - - b.Property("CouponTemplateId") - .HasColumnType("bigint") - .HasComment("模板标识。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("发放时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID(已使用时记录)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedAt") - .HasColumnType("timestamp with time zone") - .HasComment("使用时间。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("归属用户。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("coupons", null, t => - { - t.HasComment("用户领取的券。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.CouponTemplate", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowStack") - .HasColumnType("boolean") - .HasComment("是否允许叠加其他优惠。"); - - b.Property("ChannelsJson") - .HasColumnType("text") - .HasComment("发放渠道(JSON)。"); - - b.Property("ClaimedQuantity") - .HasColumnType("integer") - .HasComment("已领取数量。"); - - b.Property("CouponType") - .HasColumnType("integer") - .HasComment("券类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("DiscountCap") - .HasColumnType("numeric") - .HasComment("折扣上限(针对折扣券)。"); - - b.Property("MinimumSpend") - .HasColumnType("numeric") - .HasComment("最低消费门槛。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("模板名称。"); - - b.Property("ProductScopeJson") - .HasColumnType("text") - .HasComment("适用品类或商品范围(JSON)。"); - - b.Property("RelativeValidDays") - .HasColumnType("integer") - .HasComment("有效天数(相对发放时间)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreScopeJson") - .HasColumnType("text") - .HasComment("适用门店 ID 集合(JSON)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TotalQuantity") - .HasColumnType("integer") - .HasComment("总发放数量上限。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ValidFrom") - .HasColumnType("timestamp with time zone") - .HasComment("可用开始时间。"); - - b.Property("ValidTo") - .HasColumnType("timestamp with time zone") - .HasComment("可用结束时间。"); - - b.Property("Value") - .HasColumnType("numeric") - .HasComment("面值或折扣额度。"); - - b.HasKey("Id"); - - b.ToTable("coupon_templates", null, t => - { - t.HasComment("优惠券模板。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.PromotionCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AudienceDescription") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("目标人群描述。"); - - b.Property("BannerUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营销素材(如 banner)。"); - - b.Property("Budget") - .HasColumnType("numeric") - .HasComment("预算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("PromotionType") - .HasColumnType("integer") - .HasComment("活动类型。"); - - b.Property("RulesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("活动规则 JSON。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("活动状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("promotion_campaigns", null, t => - { - t.HasComment("营销活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChatSessionId") - .HasColumnType("bigint") - .HasComment("会话标识。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("消息内容。"); - - b.Property("ContentType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("消息类型(文字/图片/语音等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRead") - .HasColumnType("boolean") - .HasComment("是否已读。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("读取时间。"); - - b.Property("SenderType") - .HasColumnType("integer") - .HasComment("发送方类型。"); - - b.Property("SenderUserId") - .HasColumnType("bigint") - .HasComment("发送方用户 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ChatSessionId", "CreatedAt"); - - b.ToTable("chat_messages", null, t => - { - t.HasComment("会话消息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AgentUserId") - .HasColumnType("bigint") - .HasComment("当前客服员工 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("顾客用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndedAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("IsBotActive") - .HasColumnType("boolean") - .HasComment("是否机器人接待中。"); - - b.Property("SessionCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话编号。"); - - b.Property("StartedAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店(可空为平台)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionCode") - .IsUnique(); - - b.ToTable("chat_sessions", null, t => - { - t.HasComment("客服会话。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.SupportTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AssignedAgentId") - .HasColumnType("bigint") - .HasComment("指派的客服。"); - - b.Property("ClosedAt") - .HasColumnType("timestamp with time zone") - .HasComment("关闭时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("客户用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .IsRequired() - .HasColumnType("text") - .HasComment("工单详情。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单(如有)。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("优先级。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("Subject") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("工单主题。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("工单编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TicketNo") - .IsUnique(); - - b.ToTable("support_tickets", null, t => - { - t.HasComment("客服工单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.TicketComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttachmentsJson") - .HasColumnType("text") - .HasComment("附件 JSON。"); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人 ID。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsInternal") - .HasColumnType("boolean") - .HasComment("是否内部备注。"); - - b.Property("SupportTicketId") - .HasColumnType("bigint") - .HasComment("工单标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SupportTicketId"); - - b.ToTable("ticket_comments", null, t => - { - t.HasComment("工单评论/流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryEvent", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryOrderId") - .HasColumnType("bigint") - .HasComment("配送单标识。"); - - b.Property("EventType") - .HasColumnType("integer") - .HasComment("事件类型。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("事件描述。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始数据 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DeliveryOrderId", "EventType"); - - b.ToTable("delivery_events", null, t => - { - t.HasComment("配送状态事件流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CourierName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("骑手姓名。"); - - b.Property("CourierPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("骑手电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveredAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("DispatchedAt") - .HasColumnType("timestamp with time zone") - .HasComment("下发时间。"); - - b.Property("FailureReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("异常原因。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("获取或设置关联订单 ID。"); - - b.Property("PickedUpAt") - .HasColumnType("timestamp with time zone") - .HasComment("取餐时间。"); - - b.Property("Provider") - .HasColumnType("integer") - .HasComment("配送服务商。"); - - b.Property("ProviderOrderId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方配送单号。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId") - .IsUnique(); - - b.ToTable("delivery_orders", null, t => - { - t.HasComment("配送单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliateOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("推广人标识。"); - - b.Property("BuyerUserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedCommission") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("预计佣金。"); - - b.Property("OrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("订单金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("SettledAt") - .HasColumnType("timestamp with time zone") - .HasComment("结算完成时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "OrderId") - .IsUnique(); - - b.ToTable("affiliate_orders", null, t => - { - t.HasComment("分销订单记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePartner", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChannelType") - .HasColumnType("integer") - .HasComment("渠道类型。"); - - b.Property("CommissionRate") - .HasColumnType("numeric") - .HasComment("分成比例(0-1)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称或渠道名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID(如绑定平台账号)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DisplayName"); - - b.ToTable("affiliate_partners", null, t => - { - t.HasComment("分销/推广合作伙伴。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePayout", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("合作伙伴标识。"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("结算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("打款时间。"); - - b.Property("Period") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("结算周期描述。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "Period") - .IsUnique(); - - b.ToTable("affiliate_payouts", null, t => - { - t.HasComment("佣金结算记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowMakeupCount") - .HasColumnType("integer") - .HasComment("支持补签次数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("活动描述。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("结束日期。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("RewardsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("连签奖励 JSON。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("开始日期。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name"); - - b.ToTable("checkin_campaigns", null, t => - { - t.HasComment("签到活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CheckInCampaignId") - .HasColumnType("bigint") - .HasComment("活动标识。"); - - b.Property("CheckInDate") - .HasColumnType("timestamp with time zone") - .HasComment("签到日期(本地)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsMakeup") - .HasColumnType("boolean") - .HasComment("是否补签。"); - - b.Property("RewardJson") - .IsRequired() - .HasColumnType("text") - .HasComment("获得奖励 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "CheckInCampaignId", "UserId", "CheckInDate") - .IsUnique(); - - b.ToTable("checkin_records", null, t => - { - t.HasComment("用户签到记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsDeleted") - .HasColumnType("boolean") - .HasComment("状态。"); - - b.Property("ParentId") - .HasColumnType("bigint") - .HasComment("父级评论 ID。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "CreatedAt"); - - b.ToTable("community_comments", null, t => - { - t.HasComment("社区评论。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityPost", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("作者用户 ID。"); - - b.Property("CommentCount") - .HasColumnType("integer") - .HasComment("评论数。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LikeCount") - .HasColumnType("integer") - .HasComment("点赞数。"); - - b.Property("MediaJson") - .HasColumnType("text") - .HasComment("媒体资源 JSON。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AuthorUserId", "CreatedAt"); - - b.ToTable("community_posts", null, t => - { - t.HasComment("社区动态。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityReaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态 ID。"); - - b.Property("ReactedAt") - .HasColumnType("timestamp with time zone") - .HasComment("时间戳。"); - - b.Property("ReactionType") - .HasColumnType("integer") - .HasComment("反应类型。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "UserId") - .IsUnique(); - - b.ToTable("community_reactions", null, t => - { - t.HasComment("社区互动反馈。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentCount") - .HasColumnType("integer") - .HasComment("当前已参与人数。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("GroupOrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("拼单编号。"); - - b.Property("GroupPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("拼团价格。"); - - b.Property("LeaderUserId") - .HasColumnType("bigint") - .HasComment("团长用户 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("关联商品或套餐。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("拼团状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("SucceededAt") - .HasColumnType("timestamp with time zone") - .HasComment("成团时间。"); - - b.Property("TargetCount") - .HasColumnType("integer") - .HasComment("成团需要的人数。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderNo") - .IsUnique(); - - b.ToTable("group_orders", null, t => - { - t.HasComment("拼单活动。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupParticipant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GroupOrderId") - .HasColumnType("bigint") - .HasComment("拼单活动标识。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("参与时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("对应订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("参与状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderId", "UserId") - .IsUnique(); - - b.ToTable("group_participants", null, t => - { - t.HasComment("拼单参与者。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryAdjustment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdjustmentType") - .HasColumnType("integer") - .HasComment("调整类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("InventoryItemId") - .HasColumnType("bigint") - .HasComment("对应的库存记录标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("调整数量,正数增加,负数减少。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("原因说明。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "InventoryItemId", "OccurredAt"); - - b.ToTable("inventory_adjustments", null, t => - { - t.HasComment("库存调整记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryBatch", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("ProductionDate") - .HasColumnType("timestamp with time zone") - .HasComment("生产日期。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("入库数量。"); - - b.Property("RemainingQuantity") - .HasColumnType("integer") - .HasComment("剩余数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber") - .IsUnique(); - - b.ToTable("inventory_batches", null, t => - { - t.HasComment("SKU 批次信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchConsumeStrategy") - .HasColumnType("integer") - .HasComment("批次扣减策略。"); - - b.Property("BatchNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号,可为空表示混批。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售商品。"); - - b.Property("IsSoldOut") - .HasColumnType("boolean") - .HasComment("是否标记售罄。"); - - b.Property("Location") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("储位或仓位信息。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单品限购(覆盖商品级 MaxQuantityPerOrder)。"); - - b.Property("PresaleCapacity") - .HasColumnType("integer") - .HasComment("预售名额(上限)。"); - - b.Property("PresaleEndTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售结束时间(UTC)。"); - - b.Property("PresaleLocked") - .HasColumnType("integer") - .HasComment("当前预售已锁定数量。"); - - b.Property("PresaleStartTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售开始时间(UTC)。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("QuantityOnHand") - .HasColumnType("integer") - .HasComment("可用库存。"); - - b.Property("QuantityReserved") - .HasColumnType("integer") - .HasComment("已锁定库存(订单占用)。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("SafetyStock") - .HasColumnType("integer") - .HasComment("安全库存阈值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber"); - - b.ToTable("inventory_items", null, t => - { - t.HasComment("SKU 在门店的库存信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryLockRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("IdempotencyKey") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("幂等键。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售锁定。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU ID。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("锁定数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("锁定状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "IdempotencyKey") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "Status"); - - b.ToTable("inventory_lock_records", null, t => - { - t.HasComment("库存锁定记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberGrowthLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChangeValue") - .HasColumnType("integer") - .HasComment("变动数量。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentValue") - .HasColumnType("integer") - .HasComment("当前成长值。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_growth_logs", null, t => - { - t.HasComment("成长值变动日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberPointLedger", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BalanceAfterChange") - .HasColumnType("integer") - .HasComment("变动后余额。"); - - b.Property("ChangeAmount") - .HasColumnType("integer") - .HasComment("变动数量,可为负值。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(如适用)。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Reason") - .HasColumnType("integer") - .HasComment("变动原因。"); - - b.Property("SourceId") - .HasColumnType("bigint") - .HasComment("来源 ID(订单、活动等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_point_ledgers", null, t => - { - t.HasComment("积分变动流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AvatarUrl") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像。"); - - b.Property("BirthDate") - .HasColumnType("timestamp with time zone") - .HasComment("生日。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GrowthValue") - .HasColumnType("integer") - .HasComment("成长值/经验值。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("注册时间。"); - - b.Property("MemberTierId") - .HasColumnType("bigint") - .HasComment("当前会员等级 ID。"); - - b.Property("Mobile") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("Nickname") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称。"); - - b.Property("PointsBalance") - .HasColumnType("integer") - .HasComment("会员积分余额。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会员状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Mobile") - .IsUnique(); - - b.ToTable("member_profiles", null, t => - { - t.HasComment("会员档案。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberTier", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BenefitsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("等级权益(JSON)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("等级名称。"); - - b.Property("RequiredGrowth") - .HasColumnType("integer") - .HasComment("所需成长值。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("member_tiers", null, t => - { - t.HasComment("会员等级定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.Merchant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("BrandAlias") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("品牌简称或别名。"); - - b.Property("BrandName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("品牌名称(对外展示)。"); - - b.Property("BusinessLicenseImageUrl") - .HasColumnType("text") - .HasComment("营业执照扫描件地址。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照号。"); - - b.Property("Category") - .HasColumnType("text") - .HasComment("品牌所属品类,如火锅、咖啡等。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("联系邮箱。"); - - b.Property("ContactPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在区县。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("入驻时间。"); - - b.Property("LastReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次审核时间。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度信息。"); - - b.Property("LegalPerson") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人或负责人姓名。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("品牌 Logo。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度信息。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注或驳回原因。"); - - b.Property("ServicePhone") - .HasColumnType("text") - .HasComment("客服电话。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("入驻状态。"); - - b.Property("SupportEmail") - .HasColumnType("text") - .HasComment("客服邮箱。"); - - b.Property("TaxNumber") - .HasColumnType("text") - .HasComment("税号/统一社会信用代码。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.ToTable("merchants", null, t => - { - t.HasComment("商户主体信息,承载入驻和资质审核结果。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantAuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("动作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("详情描述。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("商户标识。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId"); - - b.ToTable("merchant_audit_logs", null, t => - { - t.HasComment("商户入驻审核日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("显示顺序,越小越靠前。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否可用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("类目名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("merchant_categories", null, t => - { - t.HasComment("商户可选类目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantContract", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ContractNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("合同编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同结束时间。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("合同文件存储地址。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("SignedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签署时间。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("合同状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TerminatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("终止时间。"); - - b.Property("TerminationReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("终止原因。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "ContractNumber") - .IsUnique(); - - b.ToTable("merchant_contracts", null, t => - { - t.HasComment("商户合同记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantDocument", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DocumentNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("证照编号。"); - - b.Property("DocumentType") - .HasColumnType("integer") - .HasComment("证照类型。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期日期。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("证照文件链接。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签发日期。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Remarks") - .HasColumnType("text") - .HasComment("审核备注或驳回原因。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("审核状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "DocumentType"); - - b.ToTable("merchant_documents", null, t => - { - t.HasComment("商户提交的资质或证照材料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantStaff", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Email") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("邮箱地址。"); - - b.Property("IdentityUserId") - .HasColumnType("bigint") - .HasComment("登录账号 ID(指向统一身份体系)。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("员工姓名。"); - - b.Property("PermissionsJson") - .HasColumnType("text") - .HasComment("自定义权限(JSON)。"); - - b.Property("Phone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("员工角色类型。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("员工状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("可选的关联门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "Phone"); - - b.ToTable("merchant_staff", null, t => - { - t.HasComment("商户员工账号,支持门店维度分配。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.MapLocation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Landmark") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("打车/导航落点描述。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("名称。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店 ID,可空表示独立 POI。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("map_locations", null, t => - { - t.HasComment("地图 POI 信息,用于门店定位和推荐。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.NavigationRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("来源通道(小程序、H5 等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("请求时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TargetApp") - .HasColumnType("integer") - .HasComment("跳转的地图应用。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId", "RequestedAt"); - - b.ToTable("navigation_requests", null, t => - { - t.HasComment("用户发起的导航请求日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("扩展 JSON(规格、加料选项等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品或 SKU 标识。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称快照。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("自定义备注(口味要求)。"); - - b.Property("ShoppingCartId") - .HasColumnType("bigint") - .HasComment("所属购物车标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价快照。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ShoppingCartId"); - - b.ToTable("cart_items", null, t => - { - t.HasComment("购物车条目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItemAddon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CartItemId") - .HasColumnType("bigint") - .HasComment("所属购物车条目。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("OptionId") - .HasColumnType("bigint") - .HasComment("选项 ID(可对应 ProductAddonOption)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("cart_item_addons", null, t => - { - t.HasComment("购物车条目的加料/附加项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CheckoutSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("SessionToken") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话 Token。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.Property("ValidationResultJson") - .IsRequired() - .HasColumnType("text") - .HasComment("校验结果明细 JSON。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionToken") - .IsUnique(); - - b.ToTable("checkout_sessions", null, t => - { - t.HasComment("结账会话,记录校验上下文。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.ShoppingCart", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryPreference") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("履约方式(堂食/自提/配送)缓存。"); - - b.Property("LastModifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次修改时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("购物车状态,包含正常/锁定。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableContext") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌码或场景标识(扫码点餐)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId") - .IsUnique(); - - b.ToTable("shopping_carts", null, t => - { - t.HasComment("用户购物车,按租户/门店隔离。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.Order", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("取消原因。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("下单渠道。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("顾客姓名。"); - - b.Property("CustomerPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("顾客手机号。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryType") - .HasColumnType("integer") - .HasComment("履约类型。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("优惠金额。"); - - b.Property("FinishedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("ItemsAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("商品总额。"); - - b.Property("OrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("订单号。"); - - b.Property("PaidAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付时间。"); - - b.Property("PayableAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额。"); - - b.Property("PaymentStatus") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("QueueNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队号(如有)。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationId") - .HasColumnType("bigint") - .HasComment("预约 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TableNo") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("就餐桌号。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "Status"); - - b.ToTable("orders", null, t => - { - t.HasComment("交易订单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("自定义属性 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("折扣金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品 ID。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("SkuName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("SKU/规格描述。"); - - b.Property("SubTotal") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("小计。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("单位。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("OrderId"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("order_items", null, t => - { - t.HasComment("订单明细。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderStatusHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注信息。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识(可为空表示系统)。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("变更后的状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId", "OccurredAt"); - - b.ToTable("order_status_histories", null, t => - { - t.HasComment("订单状态流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.RefundRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("申请金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("ProcessedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核完成时间。"); - - b.Property("Reason") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("申请原因。"); - - b.Property("RefundNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("退款单号。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("用户提交时间。"); - - b.Property("ReviewNotes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "RefundNo") - .IsUnique(); - - b.ToTable("refund_requests", null, t => - { - t.HasComment("售后/退款申请。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("支付金额。"); - - b.Property("ChannelTransactionId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方渠道单号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Method") - .HasColumnType("integer") - .HasComment("支付方式。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付完成时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始回调内容。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("错误/备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TradeNo") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("平台交易号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("payment_records", null, t => - { - t.HasComment("支付流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRefundRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("退款金额。"); - - b.Property("ChannelRefundId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("渠道退款流水号。"); - - b.Property("CompletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("渠道返回的原始数据 JSON。"); - - b.Property("PaymentRecordId") - .HasColumnType("bigint") - .HasComment("原支付记录标识。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("退款请求时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PaymentRecordId"); - - b.ToTable("payment_refund_records", null, t => - { - t.HasComment("支付渠道退款流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.Product", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CategoryId") - .HasColumnType("bigint") - .HasComment("所属分类。"); - - b.Property("CoverImage") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("主图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("商品描述。"); - - b.Property("EnableDelivery") - .HasColumnType("boolean") - .HasComment("支持配送。"); - - b.Property("EnableDineIn") - .HasColumnType("boolean") - .HasComment("支持堂食。"); - - b.Property("EnablePickup") - .HasColumnType("boolean") - .HasComment("支持自提。"); - - b.Property("GalleryImages") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Gallery 图片逗号分隔。"); - - b.Property("IsFeatured") - .HasColumnType("boolean") - .HasComment("是否热门推荐。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("最大每单限购。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("现价。"); - - b.Property("SpuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("商品编码。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("商品状态。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("库存数量(可选)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("Subtitle") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("副标题/卖点。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("售卖单位(份/杯等)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SpuCode") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("products", null, t => - { - t.HasComment("商品(SPU)信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("MaxSelect") - .HasColumnType("integer") - .HasComment("最大选择数量。"); - - b.Property("MinSelect") - .HasColumnType("integer") - .HasComment("最小选择数量。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "Name"); - - b.ToTable("product_addon_groups", null, t => - { - t.HasComment("加料/做法分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AddonGroupId") - .HasColumnType("bigint") - .HasComment("所属加料分组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选项。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("product_addon_options", null, t => - { - t.HasComment("加料选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称,例如“辣度”“份量”。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型(单选/多选)。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("显示排序。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店,可为空表示所有门店共享。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("product_attribute_groups", null, t => - { - t.HasComment("商品规格/属性分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributeGroupId") - .HasColumnType("bigint") - .HasComment("所属规格组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选中。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AttributeGroupId", "Name") - .IsUnique(); - - b.ToTable("product_attribute_options", null, t => - { - t.HasComment("商品规格选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("分类描述。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分类名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("product_categories", null, t => - { - t.HasComment("商品分类。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductMediaAsset", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Caption") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述或标题。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MediaType") - .HasColumnType("integer") - .HasComment("媒体类型。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品标识。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Url") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("媒资链接。"); - - b.HasKey("Id"); - - b.ToTable("product_media_assets", null, t => - { - t.HasComment("商品媒资素材。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductPricingRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("条件描述(JSON),如会员等级、渠道等。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效结束时间。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("特殊价格。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("RuleType") - .HasColumnType("integer") - .HasComment("策略类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StartTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效开始时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("WeekdaysJson") - .HasColumnType("text") - .HasComment("生效星期(JSON 数组)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "RuleType"); - - b.ToTable("product_pricing_rules", null, t => - { - t.HasComment("商品价格策略,支持会员价/时段价等。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductSku", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("规格属性 JSON(记录选项 ID)。"); - - b.Property("Barcode") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("条形码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("售价。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SkuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("SKU 编码。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("可售库存。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weight") - .HasPrecision(10, 3) - .HasColumnType("numeric(10,3)") - .HasComment("重量(千克)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SkuCode") - .IsUnique(); - - b.ToTable("product_skus", null, t => - { - t.HasComment("商品 SKU,记录具体规格组合价格。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Queues.Entities.QueueTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CalledAt") - .HasColumnType("timestamp with time zone") - .HasComment("叫号时间。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedWaitMinutes") - .HasColumnType("integer") - .HasComment("预计等待分钟。"); - - b.Property("ExpiredAt") - .HasColumnType("timestamp with time zone") - .HasComment("过号时间。"); - - b.Property("PartySize") - .HasColumnType("integer") - .HasComment("就餐人数。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("获取或设置所属门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNumber") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.HasIndex("TenantId", "StoreId", "TicketNumber") - .IsUnique(); - - b.ToTable("queue_tickets", null, t => - { - t.HasComment("排队叫号。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Reservations.Entities.Reservation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CheckInCode") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("核销码/到店码。"); - - b.Property("CheckedInAt") - .HasColumnType("timestamp with time zone") - .HasComment("实际签到时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("客户姓名。"); - - b.Property("CustomerPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PeopleCount") - .HasColumnType("integer") - .HasComment("用餐人数。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("预约号。"); - - b.Property("ReservationTime") - .HasColumnType("timestamp with time zone") - .HasComment("预约时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TablePreference") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌型/标签。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ReservationNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("reservations", null, t => - { - t.HasComment("预约/预订记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.Store", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("Announcement") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("门店公告。"); - - b.Property("BusinessHours") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("门店营业时段描述(备用字符串)。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("门店编码,便于扫码及外部对接。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家或地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("门店海报。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryRadiusKm") - .HasPrecision(6, 2) - .HasColumnType("numeric(6,2)") - .HasComment("默认配送半径(公里)。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("门店描述或公告。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区县信息。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("高德/腾讯地图经度。"); - - b.Property("ManagerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("门店负责人姓名。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("门店名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("门店当前运营状态。"); - - b.Property("SupportsDelivery") - .HasColumnType("boolean") - .HasComment("是否支持配送。"); - - b.Property("SupportsDineIn") - .HasColumnType("boolean") - .HasComment("是否支持堂食。"); - - b.Property("SupportsPickup") - .HasColumnType("boolean") - .HasComment("是否支持自提。"); - - b.Property("SupportsQueueing") - .HasColumnType("boolean") - .HasComment("支持排队叫号。"); - - b.Property("SupportsReservation") - .HasColumnType("boolean") - .HasComment("支持预约。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("门店标签(逗号分隔)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.HasIndex("TenantId", "MerchantId"); - - b.ToTable("stores", null, t => - { - t.HasComment("门店信息,承载营业配置与能力。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreBusinessHour", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CapacityLimit") - .HasColumnType("integer") - .HasComment("最大接待容量或单量限制。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DayOfWeek") - .HasColumnType("integer") - .HasComment("星期几,0 表示周日。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间(本地时间)。"); - - b.Property("HourType") - .HasColumnType("integer") - .HasComment("时段类型(正常营业、休息、预约等)。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间(本地时间)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "DayOfWeek"); - - b.ToTable("store_business_hours", null, t => - { - t.HasComment("门店营业时段配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreDeliveryZone", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("EstimatedMinutes") - .HasColumnType("integer") - .HasComment("预计送达分钟。"); - - b.Property("MinimumOrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("起送价。"); - - b.Property("PolygonGeoJson") - .IsRequired() - .HasColumnType("text") - .HasComment("GeoJSON 表示的多边形范围。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ZoneName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ZoneName"); - - b.ToTable("store_delivery_zones", null, t => - { - t.HasComment("门店配送范围配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreEmployeeShift", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("排班角色。"); - - b.Property("ShiftDate") - .HasColumnType("timestamp with time zone") - .HasComment("班次日期。"); - - b.Property("StaffId") - .HasColumnType("bigint") - .HasComment("员工标识。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ShiftDate", "StaffId") - .IsUnique(); - - b.ToTable("store_employee_shifts", null, t => - { - t.HasComment("门店员工排班记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreHoliday", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Date") - .HasColumnType("timestamp with time zone") - .HasComment("日期。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsClosed") - .HasColumnType("boolean") - .HasComment("是否全天闭店。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("说明内容。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Date") - .IsUnique(); - - b.ToTable("store_holidays", null, t => - { - t.HasComment("门店休息日或特殊营业日。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSetting", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowDaysAhead") - .HasColumnType("integer") - .HasComment("可预约天数(含当天)。"); - - b.Property("AllowToday") - .HasColumnType("boolean") - .HasComment("是否允许当天自提。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultCutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("默认截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单笔自提最大份数。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId") - .IsUnique(); - - b.ToTable("store_pickup_settings", null, t => - { - t.HasComment("门店自提配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSlot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("容量(份数)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("当天结束时间(UTC)。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("档期名称。"); - - b.Property("ReservedCount") - .HasColumnType("integer") - .HasComment("已占用数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("当天开始时间(UTC)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weekdays") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("适用星期(逗号分隔 1-7)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("store_pickup_slots", null, t => - { - t.HasComment("门店自提档期。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTable", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AreaId") - .HasColumnType("bigint") - .HasComment("所在区域 ID。"); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("可容纳人数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("QrCodeUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("桌码二维码地址。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前桌台状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("桌码。"); - - b.Property("Tags") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("桌台标签(堂食、快餐等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "TableCode") - .IsUnique(); - - b.ToTable("store_tables", null, t => - { - t.HasComment("桌台信息与二维码绑定。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTableArea", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("区域描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name") - .IsUnique(); - - b.ToTable("store_table_areas", null, t => - { - t.HasComment("门店桌台区域配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.Tenant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("text") - .HasComment("详细地址信息。"); - - b.Property("City") - .HasColumnType("text") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("租户短编码,作为跨系统引用的唯一标识。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("主联系人邮箱。"); - - b.Property("ContactName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("主联系人姓名。"); - - b.Property("ContactPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("主联系人电话。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家/地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("品牌海报或封面图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("服务生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("服务到期时间(UTC)。"); - - b.Property("Industry") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所属行业,如餐饮、零售等。"); - - b.Property("LegalEntityName") - .HasColumnType("text") - .HasComment("法人或公司主体名称。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("LOGO 图片地址。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("租户全称或品牌名称。"); - - b.Property("PrimaryOwnerUserId") - .HasColumnType("bigint") - .HasComment("系统内对应的租户所有者账号 ID。"); - - b.Property("Province") - .HasColumnType("text") - .HasComment("所在省份或州。"); - - b.Property("Remarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息,用于运营记录特殊说明。"); - - b.Property("ShortName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("对外展示的简称。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("租户当前状态,涵盖审核、启用、停用等场景。"); - - b.Property("SuspendedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次暂停服务时间。"); - - b.Property("SuspensionReason") - .HasColumnType("text") - .HasComment("暂停或终止的原因说明。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("业务标签集合(逗号分隔)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Website") - .HasColumnType("text") - .HasComment("官网或主要宣传链接。"); - - b.HasKey("Id"); - - b.HasIndex("Code") - .IsUnique(); - - b.HasIndex("ContactPhone") - .IsUnique(); - - b.ToTable("tenants", null, t => - { - t.HasComment("平台租户信息,描述租户的生命周期与基础资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementType") - .HasColumnType("integer") - .HasComment("公告类型。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("公告正文(可为 Markdown/HTML,前端自行渲染)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("失效时间(UTC),为空表示长期有效。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("展示优先级,数值越大越靠前。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("公告标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AnnouncementType", "IsActive"); - - b.HasIndex("TenantId", "EffectiveFrom", "EffectiveTo"); - - b.ToTable("tenant_announcements", null, t => - { - t.HasComment("租户公告。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncementRead", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementId") - .HasColumnType("bigint") - .HasComment("公告 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("已读时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("已读用户 ID(后台账号),为空表示租户级已读。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AnnouncementId", "UserId") - .IsUnique(); - - b.ToTable("tenant_announcement_reads", null, t => - { - t.HasComment("租户公告已读记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("操作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentStatus") - .HasColumnType("integer") - .HasComment("新状态。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("详细描述。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人名称。"); - - b.Property("PreviousStatus") - .HasColumnType("integer") - .HasComment("原状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("关联的租户标识。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("日志标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.ToTable("tenant_audit_logs", null, t => - { - t.HasComment("租户运营审核日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantBillingStatement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AmountDue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额。"); - - b.Property("AmountPaid") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DueDate") - .HasColumnType("timestamp with time zone") - .HasComment("到期日。"); - - b.Property("LineItemsJson") - .HasColumnType("text") - .HasComment("账单明细 JSON,记录各项费用。"); - - b.Property("PeriodEnd") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期结束时间。"); - - b.Property("PeriodStart") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期开始时间。"); - - b.Property("StatementNo") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("账单编号,供对账查询。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前付款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StatementNo") - .IsUnique(); - - b.ToTable("tenant_billing_statements", null, t => - { - t.HasComment("租户账单,用于呈现周期性收费。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantNotification", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("发布通道(站内、邮件、短信等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("通知正文。"); - - b.Property("MetadataJson") - .HasColumnType("text") - .HasComment("附加元数据 JSON。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("租户是否已阅读。"); - - b.Property("SentAt") - .HasColumnType("timestamp with time zone") - .HasComment("推送时间。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("通知重要级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("通知标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Channel", "SentAt"); - - b.ToTable("tenant_notifications", null, t => - { - t.HasComment("面向租户的站内通知或消息推送。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantPackage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("套餐描述,包含适用场景、权益等。"); - - b.Property("FeaturePoliciesJson") - .HasColumnType("text") - .HasComment("权益明细 JSON,记录自定义特性开关。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否仍启用(平台控制)。"); - - b.Property("IsAllowNewTenantPurchase") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否允许新租户购买/选择(仅影响新购)。"); - - b.Property("IsPublicVisible") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否对外可见(展示页/套餐列表可见性)。"); - - b.Property("MaxAccountCount") - .HasColumnType("integer") - .HasComment("允许创建的最大账号数。"); - - b.Property("MaxDeliveryOrders") - .HasColumnType("integer") - .HasComment("每月可调用的配送单数量上限。"); - - b.Property("MaxSmsCredits") - .HasColumnType("integer") - .HasComment("每月短信额度上限。"); - - b.Property("MaxStorageGb") - .HasColumnType("integer") - .HasComment("存储容量上限(GB)。"); - - b.Property("MaxStoreCount") - .HasColumnType("integer") - .HasComment("允许的最大门店数。"); - - b.Property("MonthlyPrice") - .HasColumnType("numeric") - .HasComment("月付价格,单位:人民币元。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("套餐名称,展示给租户的简称。"); - - b.Property("PackageType") - .HasColumnType("integer") - .HasComment("套餐分类(试用、标准、旗舰等)。"); - - b.Property("PublishStatus") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(1) - .HasComment("发布状态:0=草稿,1=已发布。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("展示排序,数值越小越靠前。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("YearlyPrice") - .HasColumnType("numeric") - .HasComment("年付价格,单位:人民币元。"); - - b.HasKey("Id"); - - b.HasIndex("IsActive", "SortOrder"); - - b.HasIndex("PublishStatus", "IsActive", "IsPublicVisible", "IsAllowNewTenantPurchase", "SortOrder"); - - b.ToTable("tenant_packages", null, t => - { - t.HasComment("平台提供的租户套餐定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaUsage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LastResetAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次重置时间。"); - - b.Property("LimitValue") - .HasColumnType("numeric") - .HasComment("当前配额上限。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型,例如门店数、短信条数等。"); - - b.Property("ResetCycle") - .HasColumnType("text") - .HasComment("配额刷新周期描述(如月、年)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedValue") - .HasColumnType("numeric") - .HasComment("已消耗的数量。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "QuotaType") - .IsUnique(); - - b.ToTable("tenant_quota_usages", null, t => - { - t.HasComment("租户配额使用情况快照。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantReviewClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ClaimedAt") - .HasColumnType("timestamp with time zone") - .HasComment("领取时间(UTC)。"); - - b.Property("ClaimedBy") - .HasColumnType("bigint") - .HasComment("领取人用户 ID。"); - - b.Property("ClaimedByName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("领取人名称(展示用快照)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReleasedAt") - .HasColumnType("timestamp with time zone") - .HasComment("释放时间(UTC),未释放时为 null。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("被领取的租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("ClaimedBy"); - - b.HasIndex("TenantId") - .IsUnique() - .HasFilter("\"ReleasedAt\" IS NULL AND \"DeletedAt\" IS NULL"); - - b.ToTable("tenant_review_claims", null, t => - { - t.HasComment("租户入驻审核领取记录(防止多管理员并发审核)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscription", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AutoRenew") - .HasColumnType("boolean") - .HasComment("是否开启自动续费。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("订阅生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("订阅到期时间(UTC)。"); - - b.Property("NextBillingDate") - .HasColumnType("timestamp with time zone") - .HasComment("下一个计费时间,配合自动续费使用。"); - - b.Property("Notes") - .HasColumnType("text") - .HasComment("运营备注信息。"); - - b.Property("ScheduledPackageId") - .HasColumnType("bigint") - .HasComment("若已排期升降配,对应的新套餐 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("订阅当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TenantPackageId") - .HasColumnType("bigint") - .HasComment("当前订阅关联的套餐标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantPackageId"); - - b.ToTable("tenant_subscriptions", null, t => - { - t.HasComment("租户套餐订阅记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscriptionHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasColumnType("numeric") - .HasComment("相关费用。"); - - b.Property("ChangeType") - .HasColumnType("integer") - .HasComment("变更类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Currency") - .HasMaxLength(8) - .HasColumnType("character varying(8)") - .HasComment("币种。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("FromPackageId") - .HasColumnType("bigint") - .HasComment("原套餐 ID。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("租户标识。"); - - b.Property("TenantSubscriptionId") - .HasColumnType("bigint") - .HasComment("对应的订阅 ID。"); - - b.Property("ToPackageId") - .HasColumnType("bigint") - .HasComment("新套餐 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantSubscriptionId"); - - b.ToTable("tenant_subscription_histories", null, t => - { - t.HasComment("租户套餐订阅变更记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantVerificationProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdditionalDataJson") - .HasColumnType("text") - .HasComment("附加资料(JSON)。"); - - b.Property("BankAccountName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("开户名。"); - - b.Property("BankAccountNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("银行账号。"); - - b.Property("BankName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("银行名称。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照编号。"); - - b.Property("BusinessLicenseUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营业执照文件地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LegalPersonIdBackUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证反面。"); - - b.Property("LegalPersonIdFrontUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证正面。"); - - b.Property("LegalPersonIdNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("法人身份证号。"); - - b.Property("LegalPersonName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人姓名。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注。"); - - b.Property("ReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核时间。"); - - b.Property("ReviewedBy") - .HasColumnType("bigint") - .HasComment("审核人 ID。"); - - b.Property("ReviewedByName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("审核人姓名。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("实名状态。"); - - b.Property("SubmittedAt") - .HasColumnType("timestamp with time zone") - .HasComment("提交时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("对应的租户标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId") - .IsUnique(); - - b.ToTable("tenant_verification_profiles", null, t => - { - t.HasComment("租户实名认证资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.HasOne("TakeoutSaaS.Domain.Orders.Entities.Order", null) - .WithMany() - .HasForeignKey("OrderId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215092810_AddTenantPackagePublishAndVisibility.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215092810_AddTenantPackagePublishAndVisibility.cs deleted file mode 100644 index a2a4156..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215092810_AddTenantPackagePublishAndVisibility.cs +++ /dev/null @@ -1,107 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - /// - public partial class AddTenantPackagePublishAndVisibility : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "LogoUrl", - table: "tenants", - type: "text", - nullable: true, - comment: "LOGO 图片地址。", - oldClrType: typeof(string), - oldType: "character varying(256)", - oldMaxLength: 256, - oldNullable: true, - oldComment: "LOGO 图片地址。"); - - migrationBuilder.AlterColumn( - name: "IsActive", - table: "tenant_packages", - type: "boolean", - nullable: false, - comment: "是否仍启用(平台控制)。", - oldClrType: typeof(bool), - oldType: "boolean", - oldComment: "是否仍可售卖。"); - - migrationBuilder.AddColumn( - name: "IsAllowNewTenantPurchase", - table: "tenant_packages", - type: "boolean", - nullable: false, - defaultValue: true, - comment: "是否允许新租户购买/选择(仅影响新购)。"); - - migrationBuilder.AddColumn( - name: "IsPublicVisible", - table: "tenant_packages", - type: "boolean", - nullable: false, - defaultValue: true, - comment: "是否对外可见(展示页/套餐列表可见性)。"); - - migrationBuilder.AddColumn( - name: "PublishStatus", - table: "tenant_packages", - type: "integer", - nullable: false, - defaultValue: 1, - comment: "发布状态:0=草稿,1=已发布。"); - - migrationBuilder.CreateIndex( - name: "IX_tenant_packages_PublishStatus_IsActive_IsPublicVisible_IsAl~", - table: "tenant_packages", - columns: new[] { "PublishStatus", "IsActive", "IsPublicVisible", "IsAllowNewTenantPurchase", "SortOrder" }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_tenant_packages_PublishStatus_IsActive_IsPublicVisible_IsAl~", - table: "tenant_packages"); - - migrationBuilder.DropColumn( - name: "IsAllowNewTenantPurchase", - table: "tenant_packages"); - - migrationBuilder.DropColumn( - name: "IsPublicVisible", - table: "tenant_packages"); - - migrationBuilder.DropColumn( - name: "PublishStatus", - table: "tenant_packages"); - - migrationBuilder.AlterColumn( - name: "LogoUrl", - table: "tenants", - type: "character varying(256)", - maxLength: 256, - nullable: true, - comment: "LOGO 图片地址。", - oldClrType: typeof(string), - oldType: "text", - oldNullable: true, - oldComment: "LOGO 图片地址。"); - - migrationBuilder.AlterColumn( - name: "IsActive", - table: "tenant_packages", - type: "boolean", - nullable: false, - comment: "是否仍可售卖。", - oldClrType: typeof(bool), - oldType: "boolean", - oldComment: "是否仍启用(平台控制)。"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215130235_ChangeTenantPackageDefaults.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215130235_ChangeTenantPackageDefaults.Designer.cs deleted file mode 100644 index 8dace28..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215130235_ChangeTenantPackageDefaults.Designer.cs +++ /dev/null @@ -1,6772 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.App.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - [DbContext(typeof(TakeoutAppDbContext))] - [Migration("20251215130235_ChangeTenantPackageDefaults")] - partial class ChangeTenantPackageDefaults - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricAlertRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionJson") - .IsRequired() - .HasColumnType("text") - .HasComment("触发条件 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Enabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("关联指标。"); - - b.Property("NotificationChannels") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("通知渠道。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("告警级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "Severity"); - - b.ToTable("metric_alert_rules", null, t => - { - t.HasComment("指标告警规则。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricDefinition", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("指标编码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultAggregation") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("默认聚合方式。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("说明。"); - - b.Property("DimensionsJson") - .HasColumnType("text") - .HasComment("维度描述 JSON。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("指标名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("metric_definitions", null, t => - { - t.HasComment("指标定义,描述可观测的数据点。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricSnapshot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DimensionKey") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("维度键(JSON)。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("指标定义 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Value") - .HasPrecision(18, 4) - .HasColumnType("numeric(18,4)") - .HasComment("数值。"); - - b.Property("WindowEnd") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口结束。"); - - b.Property("WindowStart") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口开始。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "DimensionKey", "WindowStart", "WindowEnd") - .IsUnique(); - - b.ToTable("metric_snapshots", null, t => - { - t.HasComment("指标快照,用于大盘展示。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.Coupon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("券码或序列号。"); - - b.Property("CouponTemplateId") - .HasColumnType("bigint") - .HasComment("模板标识。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("发放时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID(已使用时记录)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedAt") - .HasColumnType("timestamp with time zone") - .HasComment("使用时间。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("归属用户。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("coupons", null, t => - { - t.HasComment("用户领取的券。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.CouponTemplate", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowStack") - .HasColumnType("boolean") - .HasComment("是否允许叠加其他优惠。"); - - b.Property("ChannelsJson") - .HasColumnType("text") - .HasComment("发放渠道(JSON)。"); - - b.Property("ClaimedQuantity") - .HasColumnType("integer") - .HasComment("已领取数量。"); - - b.Property("CouponType") - .HasColumnType("integer") - .HasComment("券类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("DiscountCap") - .HasColumnType("numeric") - .HasComment("折扣上限(针对折扣券)。"); - - b.Property("MinimumSpend") - .HasColumnType("numeric") - .HasComment("最低消费门槛。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("模板名称。"); - - b.Property("ProductScopeJson") - .HasColumnType("text") - .HasComment("适用品类或商品范围(JSON)。"); - - b.Property("RelativeValidDays") - .HasColumnType("integer") - .HasComment("有效天数(相对发放时间)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreScopeJson") - .HasColumnType("text") - .HasComment("适用门店 ID 集合(JSON)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TotalQuantity") - .HasColumnType("integer") - .HasComment("总发放数量上限。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ValidFrom") - .HasColumnType("timestamp with time zone") - .HasComment("可用开始时间。"); - - b.Property("ValidTo") - .HasColumnType("timestamp with time zone") - .HasComment("可用结束时间。"); - - b.Property("Value") - .HasColumnType("numeric") - .HasComment("面值或折扣额度。"); - - b.HasKey("Id"); - - b.ToTable("coupon_templates", null, t => - { - t.HasComment("优惠券模板。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.PromotionCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AudienceDescription") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("目标人群描述。"); - - b.Property("BannerUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营销素材(如 banner)。"); - - b.Property("Budget") - .HasColumnType("numeric") - .HasComment("预算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("PromotionType") - .HasColumnType("integer") - .HasComment("活动类型。"); - - b.Property("RulesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("活动规则 JSON。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("活动状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("promotion_campaigns", null, t => - { - t.HasComment("营销活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChatSessionId") - .HasColumnType("bigint") - .HasComment("会话标识。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("消息内容。"); - - b.Property("ContentType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("消息类型(文字/图片/语音等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRead") - .HasColumnType("boolean") - .HasComment("是否已读。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("读取时间。"); - - b.Property("SenderType") - .HasColumnType("integer") - .HasComment("发送方类型。"); - - b.Property("SenderUserId") - .HasColumnType("bigint") - .HasComment("发送方用户 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ChatSessionId", "CreatedAt"); - - b.ToTable("chat_messages", null, t => - { - t.HasComment("会话消息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AgentUserId") - .HasColumnType("bigint") - .HasComment("当前客服员工 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("顾客用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndedAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("IsBotActive") - .HasColumnType("boolean") - .HasComment("是否机器人接待中。"); - - b.Property("SessionCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话编号。"); - - b.Property("StartedAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店(可空为平台)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionCode") - .IsUnique(); - - b.ToTable("chat_sessions", null, t => - { - t.HasComment("客服会话。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.SupportTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AssignedAgentId") - .HasColumnType("bigint") - .HasComment("指派的客服。"); - - b.Property("ClosedAt") - .HasColumnType("timestamp with time zone") - .HasComment("关闭时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("客户用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .IsRequired() - .HasColumnType("text") - .HasComment("工单详情。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单(如有)。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("优先级。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("Subject") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("工单主题。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("工单编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TicketNo") - .IsUnique(); - - b.ToTable("support_tickets", null, t => - { - t.HasComment("客服工单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.TicketComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttachmentsJson") - .HasColumnType("text") - .HasComment("附件 JSON。"); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人 ID。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsInternal") - .HasColumnType("boolean") - .HasComment("是否内部备注。"); - - b.Property("SupportTicketId") - .HasColumnType("bigint") - .HasComment("工单标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SupportTicketId"); - - b.ToTable("ticket_comments", null, t => - { - t.HasComment("工单评论/流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryEvent", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryOrderId") - .HasColumnType("bigint") - .HasComment("配送单标识。"); - - b.Property("EventType") - .HasColumnType("integer") - .HasComment("事件类型。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("事件描述。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始数据 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DeliveryOrderId", "EventType"); - - b.ToTable("delivery_events", null, t => - { - t.HasComment("配送状态事件流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CourierName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("骑手姓名。"); - - b.Property("CourierPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("骑手电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveredAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("DispatchedAt") - .HasColumnType("timestamp with time zone") - .HasComment("下发时间。"); - - b.Property("FailureReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("异常原因。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("获取或设置关联订单 ID。"); - - b.Property("PickedUpAt") - .HasColumnType("timestamp with time zone") - .HasComment("取餐时间。"); - - b.Property("Provider") - .HasColumnType("integer") - .HasComment("配送服务商。"); - - b.Property("ProviderOrderId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方配送单号。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId") - .IsUnique(); - - b.ToTable("delivery_orders", null, t => - { - t.HasComment("配送单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliateOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("推广人标识。"); - - b.Property("BuyerUserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedCommission") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("预计佣金。"); - - b.Property("OrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("订单金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("SettledAt") - .HasColumnType("timestamp with time zone") - .HasComment("结算完成时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "OrderId") - .IsUnique(); - - b.ToTable("affiliate_orders", null, t => - { - t.HasComment("分销订单记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePartner", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChannelType") - .HasColumnType("integer") - .HasComment("渠道类型。"); - - b.Property("CommissionRate") - .HasColumnType("numeric") - .HasComment("分成比例(0-1)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称或渠道名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID(如绑定平台账号)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DisplayName"); - - b.ToTable("affiliate_partners", null, t => - { - t.HasComment("分销/推广合作伙伴。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePayout", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("合作伙伴标识。"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("结算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("打款时间。"); - - b.Property("Period") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("结算周期描述。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "Period") - .IsUnique(); - - b.ToTable("affiliate_payouts", null, t => - { - t.HasComment("佣金结算记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowMakeupCount") - .HasColumnType("integer") - .HasComment("支持补签次数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("活动描述。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("结束日期。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("RewardsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("连签奖励 JSON。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("开始日期。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name"); - - b.ToTable("checkin_campaigns", null, t => - { - t.HasComment("签到活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CheckInCampaignId") - .HasColumnType("bigint") - .HasComment("活动标识。"); - - b.Property("CheckInDate") - .HasColumnType("timestamp with time zone") - .HasComment("签到日期(本地)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsMakeup") - .HasColumnType("boolean") - .HasComment("是否补签。"); - - b.Property("RewardJson") - .IsRequired() - .HasColumnType("text") - .HasComment("获得奖励 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "CheckInCampaignId", "UserId", "CheckInDate") - .IsUnique(); - - b.ToTable("checkin_records", null, t => - { - t.HasComment("用户签到记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsDeleted") - .HasColumnType("boolean") - .HasComment("状态。"); - - b.Property("ParentId") - .HasColumnType("bigint") - .HasComment("父级评论 ID。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "CreatedAt"); - - b.ToTable("community_comments", null, t => - { - t.HasComment("社区评论。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityPost", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("作者用户 ID。"); - - b.Property("CommentCount") - .HasColumnType("integer") - .HasComment("评论数。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LikeCount") - .HasColumnType("integer") - .HasComment("点赞数。"); - - b.Property("MediaJson") - .HasColumnType("text") - .HasComment("媒体资源 JSON。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AuthorUserId", "CreatedAt"); - - b.ToTable("community_posts", null, t => - { - t.HasComment("社区动态。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityReaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态 ID。"); - - b.Property("ReactedAt") - .HasColumnType("timestamp with time zone") - .HasComment("时间戳。"); - - b.Property("ReactionType") - .HasColumnType("integer") - .HasComment("反应类型。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "UserId") - .IsUnique(); - - b.ToTable("community_reactions", null, t => - { - t.HasComment("社区互动反馈。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentCount") - .HasColumnType("integer") - .HasComment("当前已参与人数。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("GroupOrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("拼单编号。"); - - b.Property("GroupPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("拼团价格。"); - - b.Property("LeaderUserId") - .HasColumnType("bigint") - .HasComment("团长用户 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("关联商品或套餐。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("拼团状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("SucceededAt") - .HasColumnType("timestamp with time zone") - .HasComment("成团时间。"); - - b.Property("TargetCount") - .HasColumnType("integer") - .HasComment("成团需要的人数。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderNo") - .IsUnique(); - - b.ToTable("group_orders", null, t => - { - t.HasComment("拼单活动。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupParticipant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GroupOrderId") - .HasColumnType("bigint") - .HasComment("拼单活动标识。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("参与时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("对应订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("参与状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderId", "UserId") - .IsUnique(); - - b.ToTable("group_participants", null, t => - { - t.HasComment("拼单参与者。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryAdjustment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdjustmentType") - .HasColumnType("integer") - .HasComment("调整类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("InventoryItemId") - .HasColumnType("bigint") - .HasComment("对应的库存记录标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("调整数量,正数增加,负数减少。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("原因说明。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "InventoryItemId", "OccurredAt"); - - b.ToTable("inventory_adjustments", null, t => - { - t.HasComment("库存调整记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryBatch", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("ProductionDate") - .HasColumnType("timestamp with time zone") - .HasComment("生产日期。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("入库数量。"); - - b.Property("RemainingQuantity") - .HasColumnType("integer") - .HasComment("剩余数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber") - .IsUnique(); - - b.ToTable("inventory_batches", null, t => - { - t.HasComment("SKU 批次信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchConsumeStrategy") - .HasColumnType("integer") - .HasComment("批次扣减策略。"); - - b.Property("BatchNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号,可为空表示混批。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售商品。"); - - b.Property("IsSoldOut") - .HasColumnType("boolean") - .HasComment("是否标记售罄。"); - - b.Property("Location") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("储位或仓位信息。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单品限购(覆盖商品级 MaxQuantityPerOrder)。"); - - b.Property("PresaleCapacity") - .HasColumnType("integer") - .HasComment("预售名额(上限)。"); - - b.Property("PresaleEndTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售结束时间(UTC)。"); - - b.Property("PresaleLocked") - .HasColumnType("integer") - .HasComment("当前预售已锁定数量。"); - - b.Property("PresaleStartTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售开始时间(UTC)。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("QuantityOnHand") - .HasColumnType("integer") - .HasComment("可用库存。"); - - b.Property("QuantityReserved") - .HasColumnType("integer") - .HasComment("已锁定库存(订单占用)。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("SafetyStock") - .HasColumnType("integer") - .HasComment("安全库存阈值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber"); - - b.ToTable("inventory_items", null, t => - { - t.HasComment("SKU 在门店的库存信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryLockRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("IdempotencyKey") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("幂等键。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售锁定。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU ID。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("锁定数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("锁定状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "IdempotencyKey") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "Status"); - - b.ToTable("inventory_lock_records", null, t => - { - t.HasComment("库存锁定记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberGrowthLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChangeValue") - .HasColumnType("integer") - .HasComment("变动数量。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentValue") - .HasColumnType("integer") - .HasComment("当前成长值。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_growth_logs", null, t => - { - t.HasComment("成长值变动日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberPointLedger", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BalanceAfterChange") - .HasColumnType("integer") - .HasComment("变动后余额。"); - - b.Property("ChangeAmount") - .HasColumnType("integer") - .HasComment("变动数量,可为负值。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(如适用)。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Reason") - .HasColumnType("integer") - .HasComment("变动原因。"); - - b.Property("SourceId") - .HasColumnType("bigint") - .HasComment("来源 ID(订单、活动等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_point_ledgers", null, t => - { - t.HasComment("积分变动流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AvatarUrl") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像。"); - - b.Property("BirthDate") - .HasColumnType("timestamp with time zone") - .HasComment("生日。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GrowthValue") - .HasColumnType("integer") - .HasComment("成长值/经验值。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("注册时间。"); - - b.Property("MemberTierId") - .HasColumnType("bigint") - .HasComment("当前会员等级 ID。"); - - b.Property("Mobile") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("Nickname") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称。"); - - b.Property("PointsBalance") - .HasColumnType("integer") - .HasComment("会员积分余额。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会员状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Mobile") - .IsUnique(); - - b.ToTable("member_profiles", null, t => - { - t.HasComment("会员档案。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberTier", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BenefitsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("等级权益(JSON)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("等级名称。"); - - b.Property("RequiredGrowth") - .HasColumnType("integer") - .HasComment("所需成长值。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("member_tiers", null, t => - { - t.HasComment("会员等级定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.Merchant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("BrandAlias") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("品牌简称或别名。"); - - b.Property("BrandName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("品牌名称(对外展示)。"); - - b.Property("BusinessLicenseImageUrl") - .HasColumnType("text") - .HasComment("营业执照扫描件地址。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照号。"); - - b.Property("Category") - .HasColumnType("text") - .HasComment("品牌所属品类,如火锅、咖啡等。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("联系邮箱。"); - - b.Property("ContactPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在区县。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("入驻时间。"); - - b.Property("LastReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次审核时间。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度信息。"); - - b.Property("LegalPerson") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人或负责人姓名。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("品牌 Logo。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度信息。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注或驳回原因。"); - - b.Property("ServicePhone") - .HasColumnType("text") - .HasComment("客服电话。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("入驻状态。"); - - b.Property("SupportEmail") - .HasColumnType("text") - .HasComment("客服邮箱。"); - - b.Property("TaxNumber") - .HasColumnType("text") - .HasComment("税号/统一社会信用代码。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.ToTable("merchants", null, t => - { - t.HasComment("商户主体信息,承载入驻和资质审核结果。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantAuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("动作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("详情描述。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("商户标识。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId"); - - b.ToTable("merchant_audit_logs", null, t => - { - t.HasComment("商户入驻审核日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("显示顺序,越小越靠前。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否可用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("类目名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("merchant_categories", null, t => - { - t.HasComment("商户可选类目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantContract", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ContractNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("合同编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同结束时间。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("合同文件存储地址。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("SignedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签署时间。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("合同状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TerminatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("终止时间。"); - - b.Property("TerminationReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("终止原因。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "ContractNumber") - .IsUnique(); - - b.ToTable("merchant_contracts", null, t => - { - t.HasComment("商户合同记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantDocument", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DocumentNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("证照编号。"); - - b.Property("DocumentType") - .HasColumnType("integer") - .HasComment("证照类型。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期日期。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("证照文件链接。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签发日期。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Remarks") - .HasColumnType("text") - .HasComment("审核备注或驳回原因。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("审核状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "DocumentType"); - - b.ToTable("merchant_documents", null, t => - { - t.HasComment("商户提交的资质或证照材料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantStaff", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Email") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("邮箱地址。"); - - b.Property("IdentityUserId") - .HasColumnType("bigint") - .HasComment("登录账号 ID(指向统一身份体系)。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("员工姓名。"); - - b.Property("PermissionsJson") - .HasColumnType("text") - .HasComment("自定义权限(JSON)。"); - - b.Property("Phone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("员工角色类型。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("员工状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("可选的关联门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "Phone"); - - b.ToTable("merchant_staff", null, t => - { - t.HasComment("商户员工账号,支持门店维度分配。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.MapLocation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Landmark") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("打车/导航落点描述。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("名称。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店 ID,可空表示独立 POI。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("map_locations", null, t => - { - t.HasComment("地图 POI 信息,用于门店定位和推荐。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.NavigationRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("来源通道(小程序、H5 等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("请求时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TargetApp") - .HasColumnType("integer") - .HasComment("跳转的地图应用。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId", "RequestedAt"); - - b.ToTable("navigation_requests", null, t => - { - t.HasComment("用户发起的导航请求日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("扩展 JSON(规格、加料选项等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品或 SKU 标识。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称快照。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("自定义备注(口味要求)。"); - - b.Property("ShoppingCartId") - .HasColumnType("bigint") - .HasComment("所属购物车标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价快照。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ShoppingCartId"); - - b.ToTable("cart_items", null, t => - { - t.HasComment("购物车条目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItemAddon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CartItemId") - .HasColumnType("bigint") - .HasComment("所属购物车条目。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("OptionId") - .HasColumnType("bigint") - .HasComment("选项 ID(可对应 ProductAddonOption)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("cart_item_addons", null, t => - { - t.HasComment("购物车条目的加料/附加项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CheckoutSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("SessionToken") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话 Token。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.Property("ValidationResultJson") - .IsRequired() - .HasColumnType("text") - .HasComment("校验结果明细 JSON。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionToken") - .IsUnique(); - - b.ToTable("checkout_sessions", null, t => - { - t.HasComment("结账会话,记录校验上下文。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.ShoppingCart", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryPreference") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("履约方式(堂食/自提/配送)缓存。"); - - b.Property("LastModifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次修改时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("购物车状态,包含正常/锁定。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableContext") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌码或场景标识(扫码点餐)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId") - .IsUnique(); - - b.ToTable("shopping_carts", null, t => - { - t.HasComment("用户购物车,按租户/门店隔离。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.Order", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("取消原因。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("下单渠道。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("顾客姓名。"); - - b.Property("CustomerPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("顾客手机号。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryType") - .HasColumnType("integer") - .HasComment("履约类型。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("优惠金额。"); - - b.Property("FinishedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("ItemsAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("商品总额。"); - - b.Property("OrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("订单号。"); - - b.Property("PaidAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付时间。"); - - b.Property("PayableAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额。"); - - b.Property("PaymentStatus") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("QueueNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队号(如有)。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationId") - .HasColumnType("bigint") - .HasComment("预约 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TableNo") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("就餐桌号。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "Status"); - - b.ToTable("orders", null, t => - { - t.HasComment("交易订单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("自定义属性 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("折扣金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品 ID。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("SkuName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("SKU/规格描述。"); - - b.Property("SubTotal") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("小计。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("单位。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("OrderId"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("order_items", null, t => - { - t.HasComment("订单明细。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderStatusHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注信息。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识(可为空表示系统)。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("变更后的状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId", "OccurredAt"); - - b.ToTable("order_status_histories", null, t => - { - t.HasComment("订单状态流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.RefundRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("申请金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("ProcessedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核完成时间。"); - - b.Property("Reason") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("申请原因。"); - - b.Property("RefundNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("退款单号。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("用户提交时间。"); - - b.Property("ReviewNotes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "RefundNo") - .IsUnique(); - - b.ToTable("refund_requests", null, t => - { - t.HasComment("售后/退款申请。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("支付金额。"); - - b.Property("ChannelTransactionId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方渠道单号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Method") - .HasColumnType("integer") - .HasComment("支付方式。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付完成时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始回调内容。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("错误/备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TradeNo") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("平台交易号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("payment_records", null, t => - { - t.HasComment("支付流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRefundRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("退款金额。"); - - b.Property("ChannelRefundId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("渠道退款流水号。"); - - b.Property("CompletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("渠道返回的原始数据 JSON。"); - - b.Property("PaymentRecordId") - .HasColumnType("bigint") - .HasComment("原支付记录标识。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("退款请求时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PaymentRecordId"); - - b.ToTable("payment_refund_records", null, t => - { - t.HasComment("支付渠道退款流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.Product", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CategoryId") - .HasColumnType("bigint") - .HasComment("所属分类。"); - - b.Property("CoverImage") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("主图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("商品描述。"); - - b.Property("EnableDelivery") - .HasColumnType("boolean") - .HasComment("支持配送。"); - - b.Property("EnableDineIn") - .HasColumnType("boolean") - .HasComment("支持堂食。"); - - b.Property("EnablePickup") - .HasColumnType("boolean") - .HasComment("支持自提。"); - - b.Property("GalleryImages") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Gallery 图片逗号分隔。"); - - b.Property("IsFeatured") - .HasColumnType("boolean") - .HasComment("是否热门推荐。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("最大每单限购。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("现价。"); - - b.Property("SpuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("商品编码。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("商品状态。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("库存数量(可选)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("Subtitle") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("副标题/卖点。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("售卖单位(份/杯等)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SpuCode") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("products", null, t => - { - t.HasComment("商品(SPU)信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("MaxSelect") - .HasColumnType("integer") - .HasComment("最大选择数量。"); - - b.Property("MinSelect") - .HasColumnType("integer") - .HasComment("最小选择数量。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "Name"); - - b.ToTable("product_addon_groups", null, t => - { - t.HasComment("加料/做法分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AddonGroupId") - .HasColumnType("bigint") - .HasComment("所属加料分组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选项。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("product_addon_options", null, t => - { - t.HasComment("加料选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称,例如“辣度”“份量”。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型(单选/多选)。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("显示排序。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店,可为空表示所有门店共享。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("product_attribute_groups", null, t => - { - t.HasComment("商品规格/属性分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributeGroupId") - .HasColumnType("bigint") - .HasComment("所属规格组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选中。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AttributeGroupId", "Name") - .IsUnique(); - - b.ToTable("product_attribute_options", null, t => - { - t.HasComment("商品规格选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("分类描述。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分类名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("product_categories", null, t => - { - t.HasComment("商品分类。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductMediaAsset", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Caption") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述或标题。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MediaType") - .HasColumnType("integer") - .HasComment("媒体类型。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品标识。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Url") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("媒资链接。"); - - b.HasKey("Id"); - - b.ToTable("product_media_assets", null, t => - { - t.HasComment("商品媒资素材。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductPricingRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("条件描述(JSON),如会员等级、渠道等。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效结束时间。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("特殊价格。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("RuleType") - .HasColumnType("integer") - .HasComment("策略类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StartTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效开始时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("WeekdaysJson") - .HasColumnType("text") - .HasComment("生效星期(JSON 数组)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "RuleType"); - - b.ToTable("product_pricing_rules", null, t => - { - t.HasComment("商品价格策略,支持会员价/时段价等。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductSku", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("规格属性 JSON(记录选项 ID)。"); - - b.Property("Barcode") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("条形码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("售价。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SkuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("SKU 编码。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("可售库存。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weight") - .HasPrecision(10, 3) - .HasColumnType("numeric(10,3)") - .HasComment("重量(千克)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SkuCode") - .IsUnique(); - - b.ToTable("product_skus", null, t => - { - t.HasComment("商品 SKU,记录具体规格组合价格。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Queues.Entities.QueueTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CalledAt") - .HasColumnType("timestamp with time zone") - .HasComment("叫号时间。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedWaitMinutes") - .HasColumnType("integer") - .HasComment("预计等待分钟。"); - - b.Property("ExpiredAt") - .HasColumnType("timestamp with time zone") - .HasComment("过号时间。"); - - b.Property("PartySize") - .HasColumnType("integer") - .HasComment("就餐人数。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("获取或设置所属门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNumber") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.HasIndex("TenantId", "StoreId", "TicketNumber") - .IsUnique(); - - b.ToTable("queue_tickets", null, t => - { - t.HasComment("排队叫号。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Reservations.Entities.Reservation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CheckInCode") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("核销码/到店码。"); - - b.Property("CheckedInAt") - .HasColumnType("timestamp with time zone") - .HasComment("实际签到时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("客户姓名。"); - - b.Property("CustomerPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PeopleCount") - .HasColumnType("integer") - .HasComment("用餐人数。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("预约号。"); - - b.Property("ReservationTime") - .HasColumnType("timestamp with time zone") - .HasComment("预约时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TablePreference") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌型/标签。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ReservationNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("reservations", null, t => - { - t.HasComment("预约/预订记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.Store", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("Announcement") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("门店公告。"); - - b.Property("BusinessHours") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("门店营业时段描述(备用字符串)。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("门店编码,便于扫码及外部对接。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家或地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("门店海报。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryRadiusKm") - .HasPrecision(6, 2) - .HasColumnType("numeric(6,2)") - .HasComment("默认配送半径(公里)。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("门店描述或公告。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区县信息。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("高德/腾讯地图经度。"); - - b.Property("ManagerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("门店负责人姓名。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("门店名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("门店当前运营状态。"); - - b.Property("SupportsDelivery") - .HasColumnType("boolean") - .HasComment("是否支持配送。"); - - b.Property("SupportsDineIn") - .HasColumnType("boolean") - .HasComment("是否支持堂食。"); - - b.Property("SupportsPickup") - .HasColumnType("boolean") - .HasComment("是否支持自提。"); - - b.Property("SupportsQueueing") - .HasColumnType("boolean") - .HasComment("支持排队叫号。"); - - b.Property("SupportsReservation") - .HasColumnType("boolean") - .HasComment("支持预约。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("门店标签(逗号分隔)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.HasIndex("TenantId", "MerchantId"); - - b.ToTable("stores", null, t => - { - t.HasComment("门店信息,承载营业配置与能力。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreBusinessHour", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CapacityLimit") - .HasColumnType("integer") - .HasComment("最大接待容量或单量限制。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DayOfWeek") - .HasColumnType("integer") - .HasComment("星期几,0 表示周日。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间(本地时间)。"); - - b.Property("HourType") - .HasColumnType("integer") - .HasComment("时段类型(正常营业、休息、预约等)。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间(本地时间)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "DayOfWeek"); - - b.ToTable("store_business_hours", null, t => - { - t.HasComment("门店营业时段配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreDeliveryZone", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("EstimatedMinutes") - .HasColumnType("integer") - .HasComment("预计送达分钟。"); - - b.Property("MinimumOrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("起送价。"); - - b.Property("PolygonGeoJson") - .IsRequired() - .HasColumnType("text") - .HasComment("GeoJSON 表示的多边形范围。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ZoneName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ZoneName"); - - b.ToTable("store_delivery_zones", null, t => - { - t.HasComment("门店配送范围配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreEmployeeShift", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("排班角色。"); - - b.Property("ShiftDate") - .HasColumnType("timestamp with time zone") - .HasComment("班次日期。"); - - b.Property("StaffId") - .HasColumnType("bigint") - .HasComment("员工标识。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ShiftDate", "StaffId") - .IsUnique(); - - b.ToTable("store_employee_shifts", null, t => - { - t.HasComment("门店员工排班记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreHoliday", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Date") - .HasColumnType("timestamp with time zone") - .HasComment("日期。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsClosed") - .HasColumnType("boolean") - .HasComment("是否全天闭店。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("说明内容。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Date") - .IsUnique(); - - b.ToTable("store_holidays", null, t => - { - t.HasComment("门店休息日或特殊营业日。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSetting", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowDaysAhead") - .HasColumnType("integer") - .HasComment("可预约天数(含当天)。"); - - b.Property("AllowToday") - .HasColumnType("boolean") - .HasComment("是否允许当天自提。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultCutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("默认截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单笔自提最大份数。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId") - .IsUnique(); - - b.ToTable("store_pickup_settings", null, t => - { - t.HasComment("门店自提配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSlot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("容量(份数)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("当天结束时间(UTC)。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("档期名称。"); - - b.Property("ReservedCount") - .HasColumnType("integer") - .HasComment("已占用数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("当天开始时间(UTC)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weekdays") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("适用星期(逗号分隔 1-7)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("store_pickup_slots", null, t => - { - t.HasComment("门店自提档期。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTable", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AreaId") - .HasColumnType("bigint") - .HasComment("所在区域 ID。"); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("可容纳人数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("QrCodeUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("桌码二维码地址。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前桌台状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("桌码。"); - - b.Property("Tags") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("桌台标签(堂食、快餐等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "TableCode") - .IsUnique(); - - b.ToTable("store_tables", null, t => - { - t.HasComment("桌台信息与二维码绑定。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTableArea", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("区域描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name") - .IsUnique(); - - b.ToTable("store_table_areas", null, t => - { - t.HasComment("门店桌台区域配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.Tenant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("text") - .HasComment("详细地址信息。"); - - b.Property("City") - .HasColumnType("text") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("租户短编码,作为跨系统引用的唯一标识。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("主联系人邮箱。"); - - b.Property("ContactName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("主联系人姓名。"); - - b.Property("ContactPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("主联系人电话。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家/地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("品牌海报或封面图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("服务生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("服务到期时间(UTC)。"); - - b.Property("Industry") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所属行业,如餐饮、零售等。"); - - b.Property("LegalEntityName") - .HasColumnType("text") - .HasComment("法人或公司主体名称。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("LOGO 图片地址。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("租户全称或品牌名称。"); - - b.Property("PrimaryOwnerUserId") - .HasColumnType("bigint") - .HasComment("系统内对应的租户所有者账号 ID。"); - - b.Property("Province") - .HasColumnType("text") - .HasComment("所在省份或州。"); - - b.Property("Remarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息,用于运营记录特殊说明。"); - - b.Property("ShortName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("对外展示的简称。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("租户当前状态,涵盖审核、启用、停用等场景。"); - - b.Property("SuspendedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次暂停服务时间。"); - - b.Property("SuspensionReason") - .HasColumnType("text") - .HasComment("暂停或终止的原因说明。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("业务标签集合(逗号分隔)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Website") - .HasColumnType("text") - .HasComment("官网或主要宣传链接。"); - - b.HasKey("Id"); - - b.HasIndex("Code") - .IsUnique(); - - b.HasIndex("ContactPhone") - .IsUnique(); - - b.ToTable("tenants", null, t => - { - t.HasComment("平台租户信息,描述租户的生命周期与基础资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementType") - .HasColumnType("integer") - .HasComment("公告类型。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("公告正文(可为 Markdown/HTML,前端自行渲染)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("失效时间(UTC),为空表示长期有效。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("展示优先级,数值越大越靠前。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("公告标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AnnouncementType", "IsActive"); - - b.HasIndex("TenantId", "EffectiveFrom", "EffectiveTo"); - - b.ToTable("tenant_announcements", null, t => - { - t.HasComment("租户公告。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncementRead", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementId") - .HasColumnType("bigint") - .HasComment("公告 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("已读时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("已读用户 ID(后台账号),为空表示租户级已读。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AnnouncementId", "UserId") - .IsUnique(); - - b.ToTable("tenant_announcement_reads", null, t => - { - t.HasComment("租户公告已读记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("操作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentStatus") - .HasColumnType("integer") - .HasComment("新状态。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("详细描述。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人名称。"); - - b.Property("PreviousStatus") - .HasColumnType("integer") - .HasComment("原状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("关联的租户标识。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("日志标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.ToTable("tenant_audit_logs", null, t => - { - t.HasComment("租户运营审核日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantBillingStatement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AmountDue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额。"); - - b.Property("AmountPaid") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DueDate") - .HasColumnType("timestamp with time zone") - .HasComment("到期日。"); - - b.Property("LineItemsJson") - .HasColumnType("text") - .HasComment("账单明细 JSON,记录各项费用。"); - - b.Property("PeriodEnd") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期结束时间。"); - - b.Property("PeriodStart") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期开始时间。"); - - b.Property("StatementNo") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("账单编号,供对账查询。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前付款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StatementNo") - .IsUnique(); - - b.ToTable("tenant_billing_statements", null, t => - { - t.HasComment("租户账单,用于呈现周期性收费。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantNotification", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("发布通道(站内、邮件、短信等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("通知正文。"); - - b.Property("MetadataJson") - .HasColumnType("text") - .HasComment("附加元数据 JSON。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("租户是否已阅读。"); - - b.Property("SentAt") - .HasColumnType("timestamp with time zone") - .HasComment("推送时间。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("通知重要级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("通知标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Channel", "SentAt"); - - b.ToTable("tenant_notifications", null, t => - { - t.HasComment("面向租户的站内通知或消息推送。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantPackage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("套餐描述,包含适用场景、权益等。"); - - b.Property("FeaturePoliciesJson") - .HasColumnType("text") - .HasComment("权益明细 JSON,记录自定义特性开关。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否仍启用(平台控制)。"); - - b.Property("IsAllowNewTenantPurchase") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否允许新租户购买/选择(仅影响新购)。"); - - b.Property("IsPublicVisible") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否对外可见(展示页/套餐列表可见性)。"); - - b.Property("MaxAccountCount") - .HasColumnType("integer") - .HasComment("允许创建的最大账号数。"); - - b.Property("MaxDeliveryOrders") - .HasColumnType("integer") - .HasComment("每月可调用的配送单数量上限。"); - - b.Property("MaxSmsCredits") - .HasColumnType("integer") - .HasComment("每月短信额度上限。"); - - b.Property("MaxStorageGb") - .HasColumnType("integer") - .HasComment("存储容量上限(GB)。"); - - b.Property("MaxStoreCount") - .HasColumnType("integer") - .HasComment("允许的最大门店数。"); - - b.Property("MonthlyPrice") - .HasColumnType("numeric") - .HasComment("月付价格,单位:人民币元。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("套餐名称,展示给租户的简称。"); - - b.Property("PackageType") - .HasColumnType("integer") - .HasComment("套餐分类(试用、标准、旗舰等)。"); - - b.Property("PublishStatus") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("发布状态:0=草稿,1=已发布。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("展示排序,数值越小越靠前。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("YearlyPrice") - .HasColumnType("numeric") - .HasComment("年付价格,单位:人民币元。"); - - b.HasKey("Id"); - - b.HasIndex("IsActive", "SortOrder"); - - b.HasIndex("PublishStatus", "IsActive", "IsPublicVisible", "IsAllowNewTenantPurchase", "SortOrder"); - - b.ToTable("tenant_packages", null, t => - { - t.HasComment("平台提供的租户套餐定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaUsage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LastResetAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次重置时间。"); - - b.Property("LimitValue") - .HasColumnType("numeric") - .HasComment("当前配额上限。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型,例如门店数、短信条数等。"); - - b.Property("ResetCycle") - .HasColumnType("text") - .HasComment("配额刷新周期描述(如月、年)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedValue") - .HasColumnType("numeric") - .HasComment("已消耗的数量。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "QuotaType") - .IsUnique(); - - b.ToTable("tenant_quota_usages", null, t => - { - t.HasComment("租户配额使用情况快照。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantReviewClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ClaimedAt") - .HasColumnType("timestamp with time zone") - .HasComment("领取时间(UTC)。"); - - b.Property("ClaimedBy") - .HasColumnType("bigint") - .HasComment("领取人用户 ID。"); - - b.Property("ClaimedByName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("领取人名称(展示用快照)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReleasedAt") - .HasColumnType("timestamp with time zone") - .HasComment("释放时间(UTC),未释放时为 null。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("被领取的租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("ClaimedBy"); - - b.HasIndex("TenantId") - .IsUnique() - .HasFilter("\"ReleasedAt\" IS NULL AND \"DeletedAt\" IS NULL"); - - b.ToTable("tenant_review_claims", null, t => - { - t.HasComment("租户入驻审核领取记录(防止多管理员并发审核)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscription", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AutoRenew") - .HasColumnType("boolean") - .HasComment("是否开启自动续费。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("订阅生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("订阅到期时间(UTC)。"); - - b.Property("NextBillingDate") - .HasColumnType("timestamp with time zone") - .HasComment("下一个计费时间,配合自动续费使用。"); - - b.Property("Notes") - .HasColumnType("text") - .HasComment("运营备注信息。"); - - b.Property("ScheduledPackageId") - .HasColumnType("bigint") - .HasComment("若已排期升降配,对应的新套餐 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("订阅当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TenantPackageId") - .HasColumnType("bigint") - .HasComment("当前订阅关联的套餐标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantPackageId"); - - b.ToTable("tenant_subscriptions", null, t => - { - t.HasComment("租户套餐订阅记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscriptionHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasColumnType("numeric") - .HasComment("相关费用。"); - - b.Property("ChangeType") - .HasColumnType("integer") - .HasComment("变更类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Currency") - .HasMaxLength(8) - .HasColumnType("character varying(8)") - .HasComment("币种。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("FromPackageId") - .HasColumnType("bigint") - .HasComment("原套餐 ID。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("租户标识。"); - - b.Property("TenantSubscriptionId") - .HasColumnType("bigint") - .HasComment("对应的订阅 ID。"); - - b.Property("ToPackageId") - .HasColumnType("bigint") - .HasComment("新套餐 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantSubscriptionId"); - - b.ToTable("tenant_subscription_histories", null, t => - { - t.HasComment("租户套餐订阅变更记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantVerificationProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdditionalDataJson") - .HasColumnType("text") - .HasComment("附加资料(JSON)。"); - - b.Property("BankAccountName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("开户名。"); - - b.Property("BankAccountNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("银行账号。"); - - b.Property("BankName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("银行名称。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照编号。"); - - b.Property("BusinessLicenseUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营业执照文件地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LegalPersonIdBackUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证反面。"); - - b.Property("LegalPersonIdFrontUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证正面。"); - - b.Property("LegalPersonIdNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("法人身份证号。"); - - b.Property("LegalPersonName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人姓名。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注。"); - - b.Property("ReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核时间。"); - - b.Property("ReviewedBy") - .HasColumnType("bigint") - .HasComment("审核人 ID。"); - - b.Property("ReviewedByName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("审核人姓名。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("实名状态。"); - - b.Property("SubmittedAt") - .HasColumnType("timestamp with time zone") - .HasComment("提交时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("对应的租户标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId") - .IsUnique(); - - b.ToTable("tenant_verification_profiles", null, t => - { - t.HasComment("租户实名认证资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.HasOne("TakeoutSaaS.Domain.Orders.Entities.Order", null) - .WithMany() - .HasForeignKey("OrderId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215130235_ChangeTenantPackageDefaults.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215130235_ChangeTenantPackageDefaults.cs deleted file mode 100644 index 9ec4401..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215130235_ChangeTenantPackageDefaults.cs +++ /dev/null @@ -1,42 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - /// - public partial class ChangeTenantPackageDefaults : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "PublishStatus", - table: "tenant_packages", - type: "integer", - nullable: false, - defaultValue: 0, - comment: "发布状态:0=草稿,1=已发布。", - oldClrType: typeof(int), - oldType: "integer", - oldDefaultValue: 1, - oldComment: "发布状态:0=草稿,1=已发布。"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "PublishStatus", - table: "tenant_packages", - type: "integer", - nullable: false, - defaultValue: 1, - comment: "发布状态:0=草稿,1=已发布。", - oldClrType: typeof(int), - oldType: "integer", - oldDefaultValue: 0, - oldComment: "发布状态:0=草稿,1=已发布。"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215143054_AddTenantPackageRecommendationAndTags.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215143054_AddTenantPackageRecommendationAndTags.Designer.cs deleted file mode 100644 index 712b8b3..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215143054_AddTenantPackageRecommendationAndTags.Designer.cs +++ /dev/null @@ -1,6783 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.App.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - [DbContext(typeof(TakeoutAppDbContext))] - [Migration("20251215143054_AddTenantPackageRecommendationAndTags")] - partial class AddTenantPackageRecommendationAndTags - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricAlertRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionJson") - .IsRequired() - .HasColumnType("text") - .HasComment("触发条件 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Enabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("关联指标。"); - - b.Property("NotificationChannels") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("通知渠道。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("告警级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "Severity"); - - b.ToTable("metric_alert_rules", null, t => - { - t.HasComment("指标告警规则。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricDefinition", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("指标编码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultAggregation") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("默认聚合方式。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("说明。"); - - b.Property("DimensionsJson") - .HasColumnType("text") - .HasComment("维度描述 JSON。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("指标名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("metric_definitions", null, t => - { - t.HasComment("指标定义,描述可观测的数据点。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricSnapshot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DimensionKey") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("维度键(JSON)。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("指标定义 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Value") - .HasPrecision(18, 4) - .HasColumnType("numeric(18,4)") - .HasComment("数值。"); - - b.Property("WindowEnd") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口结束。"); - - b.Property("WindowStart") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口开始。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "DimensionKey", "WindowStart", "WindowEnd") - .IsUnique(); - - b.ToTable("metric_snapshots", null, t => - { - t.HasComment("指标快照,用于大盘展示。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.Coupon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("券码或序列号。"); - - b.Property("CouponTemplateId") - .HasColumnType("bigint") - .HasComment("模板标识。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("发放时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID(已使用时记录)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedAt") - .HasColumnType("timestamp with time zone") - .HasComment("使用时间。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("归属用户。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("coupons", null, t => - { - t.HasComment("用户领取的券。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.CouponTemplate", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowStack") - .HasColumnType("boolean") - .HasComment("是否允许叠加其他优惠。"); - - b.Property("ChannelsJson") - .HasColumnType("text") - .HasComment("发放渠道(JSON)。"); - - b.Property("ClaimedQuantity") - .HasColumnType("integer") - .HasComment("已领取数量。"); - - b.Property("CouponType") - .HasColumnType("integer") - .HasComment("券类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("DiscountCap") - .HasColumnType("numeric") - .HasComment("折扣上限(针对折扣券)。"); - - b.Property("MinimumSpend") - .HasColumnType("numeric") - .HasComment("最低消费门槛。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("模板名称。"); - - b.Property("ProductScopeJson") - .HasColumnType("text") - .HasComment("适用品类或商品范围(JSON)。"); - - b.Property("RelativeValidDays") - .HasColumnType("integer") - .HasComment("有效天数(相对发放时间)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreScopeJson") - .HasColumnType("text") - .HasComment("适用门店 ID 集合(JSON)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TotalQuantity") - .HasColumnType("integer") - .HasComment("总发放数量上限。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ValidFrom") - .HasColumnType("timestamp with time zone") - .HasComment("可用开始时间。"); - - b.Property("ValidTo") - .HasColumnType("timestamp with time zone") - .HasComment("可用结束时间。"); - - b.Property("Value") - .HasColumnType("numeric") - .HasComment("面值或折扣额度。"); - - b.HasKey("Id"); - - b.ToTable("coupon_templates", null, t => - { - t.HasComment("优惠券模板。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.PromotionCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AudienceDescription") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("目标人群描述。"); - - b.Property("BannerUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营销素材(如 banner)。"); - - b.Property("Budget") - .HasColumnType("numeric") - .HasComment("预算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("PromotionType") - .HasColumnType("integer") - .HasComment("活动类型。"); - - b.Property("RulesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("活动规则 JSON。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("活动状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("promotion_campaigns", null, t => - { - t.HasComment("营销活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChatSessionId") - .HasColumnType("bigint") - .HasComment("会话标识。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("消息内容。"); - - b.Property("ContentType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("消息类型(文字/图片/语音等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRead") - .HasColumnType("boolean") - .HasComment("是否已读。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("读取时间。"); - - b.Property("SenderType") - .HasColumnType("integer") - .HasComment("发送方类型。"); - - b.Property("SenderUserId") - .HasColumnType("bigint") - .HasComment("发送方用户 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ChatSessionId", "CreatedAt"); - - b.ToTable("chat_messages", null, t => - { - t.HasComment("会话消息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AgentUserId") - .HasColumnType("bigint") - .HasComment("当前客服员工 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("顾客用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndedAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("IsBotActive") - .HasColumnType("boolean") - .HasComment("是否机器人接待中。"); - - b.Property("SessionCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话编号。"); - - b.Property("StartedAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店(可空为平台)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionCode") - .IsUnique(); - - b.ToTable("chat_sessions", null, t => - { - t.HasComment("客服会话。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.SupportTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AssignedAgentId") - .HasColumnType("bigint") - .HasComment("指派的客服。"); - - b.Property("ClosedAt") - .HasColumnType("timestamp with time zone") - .HasComment("关闭时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("客户用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .IsRequired() - .HasColumnType("text") - .HasComment("工单详情。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单(如有)。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("优先级。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("Subject") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("工单主题。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("工单编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TicketNo") - .IsUnique(); - - b.ToTable("support_tickets", null, t => - { - t.HasComment("客服工单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.TicketComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttachmentsJson") - .HasColumnType("text") - .HasComment("附件 JSON。"); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人 ID。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsInternal") - .HasColumnType("boolean") - .HasComment("是否内部备注。"); - - b.Property("SupportTicketId") - .HasColumnType("bigint") - .HasComment("工单标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SupportTicketId"); - - b.ToTable("ticket_comments", null, t => - { - t.HasComment("工单评论/流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryEvent", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryOrderId") - .HasColumnType("bigint") - .HasComment("配送单标识。"); - - b.Property("EventType") - .HasColumnType("integer") - .HasComment("事件类型。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("事件描述。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始数据 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DeliveryOrderId", "EventType"); - - b.ToTable("delivery_events", null, t => - { - t.HasComment("配送状态事件流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CourierName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("骑手姓名。"); - - b.Property("CourierPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("骑手电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveredAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("DispatchedAt") - .HasColumnType("timestamp with time zone") - .HasComment("下发时间。"); - - b.Property("FailureReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("异常原因。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("获取或设置关联订单 ID。"); - - b.Property("PickedUpAt") - .HasColumnType("timestamp with time zone") - .HasComment("取餐时间。"); - - b.Property("Provider") - .HasColumnType("integer") - .HasComment("配送服务商。"); - - b.Property("ProviderOrderId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方配送单号。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId") - .IsUnique(); - - b.ToTable("delivery_orders", null, t => - { - t.HasComment("配送单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliateOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("推广人标识。"); - - b.Property("BuyerUserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedCommission") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("预计佣金。"); - - b.Property("OrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("订单金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("SettledAt") - .HasColumnType("timestamp with time zone") - .HasComment("结算完成时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "OrderId") - .IsUnique(); - - b.ToTable("affiliate_orders", null, t => - { - t.HasComment("分销订单记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePartner", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChannelType") - .HasColumnType("integer") - .HasComment("渠道类型。"); - - b.Property("CommissionRate") - .HasColumnType("numeric") - .HasComment("分成比例(0-1)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称或渠道名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID(如绑定平台账号)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DisplayName"); - - b.ToTable("affiliate_partners", null, t => - { - t.HasComment("分销/推广合作伙伴。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePayout", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("合作伙伴标识。"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("结算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("打款时间。"); - - b.Property("Period") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("结算周期描述。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "Period") - .IsUnique(); - - b.ToTable("affiliate_payouts", null, t => - { - t.HasComment("佣金结算记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowMakeupCount") - .HasColumnType("integer") - .HasComment("支持补签次数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("活动描述。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("结束日期。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("RewardsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("连签奖励 JSON。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("开始日期。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name"); - - b.ToTable("checkin_campaigns", null, t => - { - t.HasComment("签到活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CheckInCampaignId") - .HasColumnType("bigint") - .HasComment("活动标识。"); - - b.Property("CheckInDate") - .HasColumnType("timestamp with time zone") - .HasComment("签到日期(本地)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsMakeup") - .HasColumnType("boolean") - .HasComment("是否补签。"); - - b.Property("RewardJson") - .IsRequired() - .HasColumnType("text") - .HasComment("获得奖励 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "CheckInCampaignId", "UserId", "CheckInDate") - .IsUnique(); - - b.ToTable("checkin_records", null, t => - { - t.HasComment("用户签到记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsDeleted") - .HasColumnType("boolean") - .HasComment("状态。"); - - b.Property("ParentId") - .HasColumnType("bigint") - .HasComment("父级评论 ID。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "CreatedAt"); - - b.ToTable("community_comments", null, t => - { - t.HasComment("社区评论。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityPost", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("作者用户 ID。"); - - b.Property("CommentCount") - .HasColumnType("integer") - .HasComment("评论数。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LikeCount") - .HasColumnType("integer") - .HasComment("点赞数。"); - - b.Property("MediaJson") - .HasColumnType("text") - .HasComment("媒体资源 JSON。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AuthorUserId", "CreatedAt"); - - b.ToTable("community_posts", null, t => - { - t.HasComment("社区动态。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityReaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态 ID。"); - - b.Property("ReactedAt") - .HasColumnType("timestamp with time zone") - .HasComment("时间戳。"); - - b.Property("ReactionType") - .HasColumnType("integer") - .HasComment("反应类型。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "UserId") - .IsUnique(); - - b.ToTable("community_reactions", null, t => - { - t.HasComment("社区互动反馈。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentCount") - .HasColumnType("integer") - .HasComment("当前已参与人数。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("GroupOrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("拼单编号。"); - - b.Property("GroupPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("拼团价格。"); - - b.Property("LeaderUserId") - .HasColumnType("bigint") - .HasComment("团长用户 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("关联商品或套餐。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("拼团状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("SucceededAt") - .HasColumnType("timestamp with time zone") - .HasComment("成团时间。"); - - b.Property("TargetCount") - .HasColumnType("integer") - .HasComment("成团需要的人数。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderNo") - .IsUnique(); - - b.ToTable("group_orders", null, t => - { - t.HasComment("拼单活动。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupParticipant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GroupOrderId") - .HasColumnType("bigint") - .HasComment("拼单活动标识。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("参与时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("对应订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("参与状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderId", "UserId") - .IsUnique(); - - b.ToTable("group_participants", null, t => - { - t.HasComment("拼单参与者。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryAdjustment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdjustmentType") - .HasColumnType("integer") - .HasComment("调整类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("InventoryItemId") - .HasColumnType("bigint") - .HasComment("对应的库存记录标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("调整数量,正数增加,负数减少。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("原因说明。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "InventoryItemId", "OccurredAt"); - - b.ToTable("inventory_adjustments", null, t => - { - t.HasComment("库存调整记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryBatch", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("ProductionDate") - .HasColumnType("timestamp with time zone") - .HasComment("生产日期。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("入库数量。"); - - b.Property("RemainingQuantity") - .HasColumnType("integer") - .HasComment("剩余数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber") - .IsUnique(); - - b.ToTable("inventory_batches", null, t => - { - t.HasComment("SKU 批次信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchConsumeStrategy") - .HasColumnType("integer") - .HasComment("批次扣减策略。"); - - b.Property("BatchNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号,可为空表示混批。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售商品。"); - - b.Property("IsSoldOut") - .HasColumnType("boolean") - .HasComment("是否标记售罄。"); - - b.Property("Location") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("储位或仓位信息。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单品限购(覆盖商品级 MaxQuantityPerOrder)。"); - - b.Property("PresaleCapacity") - .HasColumnType("integer") - .HasComment("预售名额(上限)。"); - - b.Property("PresaleEndTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售结束时间(UTC)。"); - - b.Property("PresaleLocked") - .HasColumnType("integer") - .HasComment("当前预售已锁定数量。"); - - b.Property("PresaleStartTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售开始时间(UTC)。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("QuantityOnHand") - .HasColumnType("integer") - .HasComment("可用库存。"); - - b.Property("QuantityReserved") - .HasColumnType("integer") - .HasComment("已锁定库存(订单占用)。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("SafetyStock") - .HasColumnType("integer") - .HasComment("安全库存阈值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber"); - - b.ToTable("inventory_items", null, t => - { - t.HasComment("SKU 在门店的库存信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryLockRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("IdempotencyKey") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("幂等键。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售锁定。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU ID。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("锁定数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("锁定状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "IdempotencyKey") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "Status"); - - b.ToTable("inventory_lock_records", null, t => - { - t.HasComment("库存锁定记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberGrowthLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChangeValue") - .HasColumnType("integer") - .HasComment("变动数量。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentValue") - .HasColumnType("integer") - .HasComment("当前成长值。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_growth_logs", null, t => - { - t.HasComment("成长值变动日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberPointLedger", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BalanceAfterChange") - .HasColumnType("integer") - .HasComment("变动后余额。"); - - b.Property("ChangeAmount") - .HasColumnType("integer") - .HasComment("变动数量,可为负值。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(如适用)。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Reason") - .HasColumnType("integer") - .HasComment("变动原因。"); - - b.Property("SourceId") - .HasColumnType("bigint") - .HasComment("来源 ID(订单、活动等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_point_ledgers", null, t => - { - t.HasComment("积分变动流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AvatarUrl") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像。"); - - b.Property("BirthDate") - .HasColumnType("timestamp with time zone") - .HasComment("生日。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GrowthValue") - .HasColumnType("integer") - .HasComment("成长值/经验值。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("注册时间。"); - - b.Property("MemberTierId") - .HasColumnType("bigint") - .HasComment("当前会员等级 ID。"); - - b.Property("Mobile") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("Nickname") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称。"); - - b.Property("PointsBalance") - .HasColumnType("integer") - .HasComment("会员积分余额。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会员状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Mobile") - .IsUnique(); - - b.ToTable("member_profiles", null, t => - { - t.HasComment("会员档案。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberTier", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BenefitsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("等级权益(JSON)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("等级名称。"); - - b.Property("RequiredGrowth") - .HasColumnType("integer") - .HasComment("所需成长值。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("member_tiers", null, t => - { - t.HasComment("会员等级定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.Merchant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("BrandAlias") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("品牌简称或别名。"); - - b.Property("BrandName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("品牌名称(对外展示)。"); - - b.Property("BusinessLicenseImageUrl") - .HasColumnType("text") - .HasComment("营业执照扫描件地址。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照号。"); - - b.Property("Category") - .HasColumnType("text") - .HasComment("品牌所属品类,如火锅、咖啡等。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("联系邮箱。"); - - b.Property("ContactPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在区县。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("入驻时间。"); - - b.Property("LastReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次审核时间。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度信息。"); - - b.Property("LegalPerson") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人或负责人姓名。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("品牌 Logo。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度信息。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注或驳回原因。"); - - b.Property("ServicePhone") - .HasColumnType("text") - .HasComment("客服电话。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("入驻状态。"); - - b.Property("SupportEmail") - .HasColumnType("text") - .HasComment("客服邮箱。"); - - b.Property("TaxNumber") - .HasColumnType("text") - .HasComment("税号/统一社会信用代码。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.ToTable("merchants", null, t => - { - t.HasComment("商户主体信息,承载入驻和资质审核结果。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantAuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("动作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("详情描述。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("商户标识。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId"); - - b.ToTable("merchant_audit_logs", null, t => - { - t.HasComment("商户入驻审核日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("显示顺序,越小越靠前。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否可用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("类目名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("merchant_categories", null, t => - { - t.HasComment("商户可选类目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantContract", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ContractNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("合同编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同结束时间。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("合同文件存储地址。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("SignedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签署时间。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("合同状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TerminatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("终止时间。"); - - b.Property("TerminationReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("终止原因。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "ContractNumber") - .IsUnique(); - - b.ToTable("merchant_contracts", null, t => - { - t.HasComment("商户合同记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantDocument", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DocumentNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("证照编号。"); - - b.Property("DocumentType") - .HasColumnType("integer") - .HasComment("证照类型。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期日期。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("证照文件链接。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签发日期。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Remarks") - .HasColumnType("text") - .HasComment("审核备注或驳回原因。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("审核状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "DocumentType"); - - b.ToTable("merchant_documents", null, t => - { - t.HasComment("商户提交的资质或证照材料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantStaff", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Email") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("邮箱地址。"); - - b.Property("IdentityUserId") - .HasColumnType("bigint") - .HasComment("登录账号 ID(指向统一身份体系)。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("员工姓名。"); - - b.Property("PermissionsJson") - .HasColumnType("text") - .HasComment("自定义权限(JSON)。"); - - b.Property("Phone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("员工角色类型。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("员工状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("可选的关联门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "Phone"); - - b.ToTable("merchant_staff", null, t => - { - t.HasComment("商户员工账号,支持门店维度分配。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.MapLocation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Landmark") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("打车/导航落点描述。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("名称。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店 ID,可空表示独立 POI。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("map_locations", null, t => - { - t.HasComment("地图 POI 信息,用于门店定位和推荐。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.NavigationRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("来源通道(小程序、H5 等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("请求时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TargetApp") - .HasColumnType("integer") - .HasComment("跳转的地图应用。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId", "RequestedAt"); - - b.ToTable("navigation_requests", null, t => - { - t.HasComment("用户发起的导航请求日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("扩展 JSON(规格、加料选项等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品或 SKU 标识。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称快照。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("自定义备注(口味要求)。"); - - b.Property("ShoppingCartId") - .HasColumnType("bigint") - .HasComment("所属购物车标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价快照。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ShoppingCartId"); - - b.ToTable("cart_items", null, t => - { - t.HasComment("购物车条目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItemAddon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CartItemId") - .HasColumnType("bigint") - .HasComment("所属购物车条目。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("OptionId") - .HasColumnType("bigint") - .HasComment("选项 ID(可对应 ProductAddonOption)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("cart_item_addons", null, t => - { - t.HasComment("购物车条目的加料/附加项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CheckoutSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("SessionToken") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话 Token。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.Property("ValidationResultJson") - .IsRequired() - .HasColumnType("text") - .HasComment("校验结果明细 JSON。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionToken") - .IsUnique(); - - b.ToTable("checkout_sessions", null, t => - { - t.HasComment("结账会话,记录校验上下文。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.ShoppingCart", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryPreference") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("履约方式(堂食/自提/配送)缓存。"); - - b.Property("LastModifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次修改时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("购物车状态,包含正常/锁定。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableContext") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌码或场景标识(扫码点餐)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId") - .IsUnique(); - - b.ToTable("shopping_carts", null, t => - { - t.HasComment("用户购物车,按租户/门店隔离。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.Order", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("取消原因。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("下单渠道。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("顾客姓名。"); - - b.Property("CustomerPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("顾客手机号。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryType") - .HasColumnType("integer") - .HasComment("履约类型。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("优惠金额。"); - - b.Property("FinishedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("ItemsAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("商品总额。"); - - b.Property("OrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("订单号。"); - - b.Property("PaidAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付时间。"); - - b.Property("PayableAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额。"); - - b.Property("PaymentStatus") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("QueueNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队号(如有)。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationId") - .HasColumnType("bigint") - .HasComment("预约 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TableNo") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("就餐桌号。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "Status"); - - b.ToTable("orders", null, t => - { - t.HasComment("交易订单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("自定义属性 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("折扣金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品 ID。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("SkuName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("SKU/规格描述。"); - - b.Property("SubTotal") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("小计。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("单位。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("OrderId"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("order_items", null, t => - { - t.HasComment("订单明细。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderStatusHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注信息。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识(可为空表示系统)。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("变更后的状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId", "OccurredAt"); - - b.ToTable("order_status_histories", null, t => - { - t.HasComment("订单状态流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.RefundRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("申请金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("ProcessedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核完成时间。"); - - b.Property("Reason") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("申请原因。"); - - b.Property("RefundNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("退款单号。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("用户提交时间。"); - - b.Property("ReviewNotes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "RefundNo") - .IsUnique(); - - b.ToTable("refund_requests", null, t => - { - t.HasComment("售后/退款申请。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("支付金额。"); - - b.Property("ChannelTransactionId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方渠道单号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Method") - .HasColumnType("integer") - .HasComment("支付方式。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付完成时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始回调内容。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("错误/备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TradeNo") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("平台交易号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("payment_records", null, t => - { - t.HasComment("支付流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRefundRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("退款金额。"); - - b.Property("ChannelRefundId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("渠道退款流水号。"); - - b.Property("CompletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("渠道返回的原始数据 JSON。"); - - b.Property("PaymentRecordId") - .HasColumnType("bigint") - .HasComment("原支付记录标识。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("退款请求时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PaymentRecordId"); - - b.ToTable("payment_refund_records", null, t => - { - t.HasComment("支付渠道退款流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.Product", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CategoryId") - .HasColumnType("bigint") - .HasComment("所属分类。"); - - b.Property("CoverImage") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("主图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("商品描述。"); - - b.Property("EnableDelivery") - .HasColumnType("boolean") - .HasComment("支持配送。"); - - b.Property("EnableDineIn") - .HasColumnType("boolean") - .HasComment("支持堂食。"); - - b.Property("EnablePickup") - .HasColumnType("boolean") - .HasComment("支持自提。"); - - b.Property("GalleryImages") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Gallery 图片逗号分隔。"); - - b.Property("IsFeatured") - .HasColumnType("boolean") - .HasComment("是否热门推荐。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("最大每单限购。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("现价。"); - - b.Property("SpuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("商品编码。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("商品状态。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("库存数量(可选)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("Subtitle") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("副标题/卖点。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("售卖单位(份/杯等)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SpuCode") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("products", null, t => - { - t.HasComment("商品(SPU)信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("MaxSelect") - .HasColumnType("integer") - .HasComment("最大选择数量。"); - - b.Property("MinSelect") - .HasColumnType("integer") - .HasComment("最小选择数量。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "Name"); - - b.ToTable("product_addon_groups", null, t => - { - t.HasComment("加料/做法分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AddonGroupId") - .HasColumnType("bigint") - .HasComment("所属加料分组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选项。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("product_addon_options", null, t => - { - t.HasComment("加料选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称,例如“辣度”“份量”。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型(单选/多选)。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("显示排序。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店,可为空表示所有门店共享。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("product_attribute_groups", null, t => - { - t.HasComment("商品规格/属性分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributeGroupId") - .HasColumnType("bigint") - .HasComment("所属规格组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选中。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AttributeGroupId", "Name") - .IsUnique(); - - b.ToTable("product_attribute_options", null, t => - { - t.HasComment("商品规格选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("分类描述。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分类名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("product_categories", null, t => - { - t.HasComment("商品分类。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductMediaAsset", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Caption") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述或标题。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MediaType") - .HasColumnType("integer") - .HasComment("媒体类型。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品标识。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Url") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("媒资链接。"); - - b.HasKey("Id"); - - b.ToTable("product_media_assets", null, t => - { - t.HasComment("商品媒资素材。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductPricingRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("条件描述(JSON),如会员等级、渠道等。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效结束时间。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("特殊价格。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("RuleType") - .HasColumnType("integer") - .HasComment("策略类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StartTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效开始时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("WeekdaysJson") - .HasColumnType("text") - .HasComment("生效星期(JSON 数组)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "RuleType"); - - b.ToTable("product_pricing_rules", null, t => - { - t.HasComment("商品价格策略,支持会员价/时段价等。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductSku", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("规格属性 JSON(记录选项 ID)。"); - - b.Property("Barcode") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("条形码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("售价。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SkuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("SKU 编码。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("可售库存。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weight") - .HasPrecision(10, 3) - .HasColumnType("numeric(10,3)") - .HasComment("重量(千克)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SkuCode") - .IsUnique(); - - b.ToTable("product_skus", null, t => - { - t.HasComment("商品 SKU,记录具体规格组合价格。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Queues.Entities.QueueTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CalledAt") - .HasColumnType("timestamp with time zone") - .HasComment("叫号时间。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedWaitMinutes") - .HasColumnType("integer") - .HasComment("预计等待分钟。"); - - b.Property("ExpiredAt") - .HasColumnType("timestamp with time zone") - .HasComment("过号时间。"); - - b.Property("PartySize") - .HasColumnType("integer") - .HasComment("就餐人数。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("获取或设置所属门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNumber") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.HasIndex("TenantId", "StoreId", "TicketNumber") - .IsUnique(); - - b.ToTable("queue_tickets", null, t => - { - t.HasComment("排队叫号。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Reservations.Entities.Reservation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CheckInCode") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("核销码/到店码。"); - - b.Property("CheckedInAt") - .HasColumnType("timestamp with time zone") - .HasComment("实际签到时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("客户姓名。"); - - b.Property("CustomerPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PeopleCount") - .HasColumnType("integer") - .HasComment("用餐人数。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("预约号。"); - - b.Property("ReservationTime") - .HasColumnType("timestamp with time zone") - .HasComment("预约时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TablePreference") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌型/标签。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ReservationNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("reservations", null, t => - { - t.HasComment("预约/预订记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.Store", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("Announcement") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("门店公告。"); - - b.Property("BusinessHours") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("门店营业时段描述(备用字符串)。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("门店编码,便于扫码及外部对接。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家或地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("门店海报。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryRadiusKm") - .HasPrecision(6, 2) - .HasColumnType("numeric(6,2)") - .HasComment("默认配送半径(公里)。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("门店描述或公告。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区县信息。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("高德/腾讯地图经度。"); - - b.Property("ManagerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("门店负责人姓名。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("门店名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("门店当前运营状态。"); - - b.Property("SupportsDelivery") - .HasColumnType("boolean") - .HasComment("是否支持配送。"); - - b.Property("SupportsDineIn") - .HasColumnType("boolean") - .HasComment("是否支持堂食。"); - - b.Property("SupportsPickup") - .HasColumnType("boolean") - .HasComment("是否支持自提。"); - - b.Property("SupportsQueueing") - .HasColumnType("boolean") - .HasComment("支持排队叫号。"); - - b.Property("SupportsReservation") - .HasColumnType("boolean") - .HasComment("支持预约。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("门店标签(逗号分隔)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.HasIndex("TenantId", "MerchantId"); - - b.ToTable("stores", null, t => - { - t.HasComment("门店信息,承载营业配置与能力。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreBusinessHour", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CapacityLimit") - .HasColumnType("integer") - .HasComment("最大接待容量或单量限制。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DayOfWeek") - .HasColumnType("integer") - .HasComment("星期几,0 表示周日。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间(本地时间)。"); - - b.Property("HourType") - .HasColumnType("integer") - .HasComment("时段类型(正常营业、休息、预约等)。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间(本地时间)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "DayOfWeek"); - - b.ToTable("store_business_hours", null, t => - { - t.HasComment("门店营业时段配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreDeliveryZone", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("EstimatedMinutes") - .HasColumnType("integer") - .HasComment("预计送达分钟。"); - - b.Property("MinimumOrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("起送价。"); - - b.Property("PolygonGeoJson") - .IsRequired() - .HasColumnType("text") - .HasComment("GeoJSON 表示的多边形范围。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ZoneName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ZoneName"); - - b.ToTable("store_delivery_zones", null, t => - { - t.HasComment("门店配送范围配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreEmployeeShift", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("排班角色。"); - - b.Property("ShiftDate") - .HasColumnType("timestamp with time zone") - .HasComment("班次日期。"); - - b.Property("StaffId") - .HasColumnType("bigint") - .HasComment("员工标识。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ShiftDate", "StaffId") - .IsUnique(); - - b.ToTable("store_employee_shifts", null, t => - { - t.HasComment("门店员工排班记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreHoliday", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Date") - .HasColumnType("timestamp with time zone") - .HasComment("日期。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsClosed") - .HasColumnType("boolean") - .HasComment("是否全天闭店。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("说明内容。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Date") - .IsUnique(); - - b.ToTable("store_holidays", null, t => - { - t.HasComment("门店休息日或特殊营业日。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSetting", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowDaysAhead") - .HasColumnType("integer") - .HasComment("可预约天数(含当天)。"); - - b.Property("AllowToday") - .HasColumnType("boolean") - .HasComment("是否允许当天自提。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultCutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("默认截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单笔自提最大份数。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId") - .IsUnique(); - - b.ToTable("store_pickup_settings", null, t => - { - t.HasComment("门店自提配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSlot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("容量(份数)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("当天结束时间(UTC)。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("档期名称。"); - - b.Property("ReservedCount") - .HasColumnType("integer") - .HasComment("已占用数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("当天开始时间(UTC)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weekdays") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("适用星期(逗号分隔 1-7)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("store_pickup_slots", null, t => - { - t.HasComment("门店自提档期。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTable", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AreaId") - .HasColumnType("bigint") - .HasComment("所在区域 ID。"); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("可容纳人数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("QrCodeUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("桌码二维码地址。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前桌台状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("桌码。"); - - b.Property("Tags") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("桌台标签(堂食、快餐等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "TableCode") - .IsUnique(); - - b.ToTable("store_tables", null, t => - { - t.HasComment("桌台信息与二维码绑定。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTableArea", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("区域描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name") - .IsUnique(); - - b.ToTable("store_table_areas", null, t => - { - t.HasComment("门店桌台区域配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.Tenant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("text") - .HasComment("详细地址信息。"); - - b.Property("City") - .HasColumnType("text") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("租户短编码,作为跨系统引用的唯一标识。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("主联系人邮箱。"); - - b.Property("ContactName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("主联系人姓名。"); - - b.Property("ContactPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("主联系人电话。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家/地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("品牌海报或封面图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("服务生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("服务到期时间(UTC)。"); - - b.Property("Industry") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所属行业,如餐饮、零售等。"); - - b.Property("LegalEntityName") - .HasColumnType("text") - .HasComment("法人或公司主体名称。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("LOGO 图片地址。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("租户全称或品牌名称。"); - - b.Property("PrimaryOwnerUserId") - .HasColumnType("bigint") - .HasComment("系统内对应的租户所有者账号 ID。"); - - b.Property("Province") - .HasColumnType("text") - .HasComment("所在省份或州。"); - - b.Property("Remarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息,用于运营记录特殊说明。"); - - b.Property("ShortName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("对外展示的简称。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("租户当前状态,涵盖审核、启用、停用等场景。"); - - b.Property("SuspendedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次暂停服务时间。"); - - b.Property("SuspensionReason") - .HasColumnType("text") - .HasComment("暂停或终止的原因说明。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("业务标签集合(逗号分隔)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Website") - .HasColumnType("text") - .HasComment("官网或主要宣传链接。"); - - b.HasKey("Id"); - - b.HasIndex("Code") - .IsUnique(); - - b.HasIndex("ContactPhone") - .IsUnique(); - - b.ToTable("tenants", null, t => - { - t.HasComment("平台租户信息,描述租户的生命周期与基础资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementType") - .HasColumnType("integer") - .HasComment("公告类型。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("公告正文(可为 Markdown/HTML,前端自行渲染)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("失效时间(UTC),为空表示长期有效。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("展示优先级,数值越大越靠前。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("公告标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AnnouncementType", "IsActive"); - - b.HasIndex("TenantId", "EffectiveFrom", "EffectiveTo"); - - b.ToTable("tenant_announcements", null, t => - { - t.HasComment("租户公告。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncementRead", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementId") - .HasColumnType("bigint") - .HasComment("公告 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("已读时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("已读用户 ID(后台账号),为空表示租户级已读。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AnnouncementId", "UserId") - .IsUnique(); - - b.ToTable("tenant_announcement_reads", null, t => - { - t.HasComment("租户公告已读记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("操作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentStatus") - .HasColumnType("integer") - .HasComment("新状态。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("详细描述。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人名称。"); - - b.Property("PreviousStatus") - .HasColumnType("integer") - .HasComment("原状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("关联的租户标识。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("日志标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.ToTable("tenant_audit_logs", null, t => - { - t.HasComment("租户运营审核日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantBillingStatement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AmountDue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额。"); - - b.Property("AmountPaid") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DueDate") - .HasColumnType("timestamp with time zone") - .HasComment("到期日。"); - - b.Property("LineItemsJson") - .HasColumnType("text") - .HasComment("账单明细 JSON,记录各项费用。"); - - b.Property("PeriodEnd") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期结束时间。"); - - b.Property("PeriodStart") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期开始时间。"); - - b.Property("StatementNo") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("账单编号,供对账查询。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前付款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StatementNo") - .IsUnique(); - - b.ToTable("tenant_billing_statements", null, t => - { - t.HasComment("租户账单,用于呈现周期性收费。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantNotification", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("发布通道(站内、邮件、短信等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("通知正文。"); - - b.Property("MetadataJson") - .HasColumnType("text") - .HasComment("附加元数据 JSON。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("租户是否已阅读。"); - - b.Property("SentAt") - .HasColumnType("timestamp with time zone") - .HasComment("推送时间。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("通知重要级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("通知标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Channel", "SentAt"); - - b.ToTable("tenant_notifications", null, t => - { - t.HasComment("面向租户的站内通知或消息推送。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantPackage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("套餐描述,包含适用场景、权益等。"); - - b.Property("FeaturePoliciesJson") - .HasColumnType("text") - .HasComment("权益明细 JSON,记录自定义特性开关。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否仍启用(平台控制)。"); - - b.Property("IsAllowNewTenantPurchase") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否允许新租户购买/选择(仅影响新购)。"); - - b.Property("IsPublicVisible") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否对外可见(展示页/套餐列表可见性)。"); - - b.Property("IsRecommended") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false) - .HasComment("是否推荐展示(运营推荐标识)。"); - - b.Property("MaxAccountCount") - .HasColumnType("integer") - .HasComment("允许创建的最大账号数。"); - - b.Property("MaxDeliveryOrders") - .HasColumnType("integer") - .HasComment("每月可调用的配送单数量上限。"); - - b.Property("MaxSmsCredits") - .HasColumnType("integer") - .HasComment("每月短信额度上限。"); - - b.Property("MaxStorageGb") - .HasColumnType("integer") - .HasComment("存储容量上限(GB)。"); - - b.Property("MaxStoreCount") - .HasColumnType("integer") - .HasComment("允许的最大门店数。"); - - b.Property("MonthlyPrice") - .HasColumnType("numeric") - .HasComment("月付价格,单位:人民币元。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("套餐名称,展示给租户的简称。"); - - b.Property("PackageType") - .HasColumnType("integer") - .HasComment("套餐分类(试用、标准、旗舰等)。"); - - b.Property("PublishStatus") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("发布状态:0=草稿,1=已发布。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("展示排序,数值越小越靠前。"); - - b.PrimitiveCollection("Tags") - .IsRequired() - .HasColumnType("text[]") - .HasComment("套餐标签(用于展示与对比页)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("YearlyPrice") - .HasColumnType("numeric") - .HasComment("年付价格,单位:人民币元。"); - - b.HasKey("Id"); - - b.HasIndex("IsActive", "SortOrder"); - - b.HasIndex("PublishStatus", "IsActive", "IsPublicVisible", "IsAllowNewTenantPurchase", "SortOrder"); - - b.ToTable("tenant_packages", null, t => - { - t.HasComment("平台提供的租户套餐定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaUsage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LastResetAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次重置时间。"); - - b.Property("LimitValue") - .HasColumnType("numeric") - .HasComment("当前配额上限。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型,例如门店数、短信条数等。"); - - b.Property("ResetCycle") - .HasColumnType("text") - .HasComment("配额刷新周期描述(如月、年)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedValue") - .HasColumnType("numeric") - .HasComment("已消耗的数量。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "QuotaType") - .IsUnique(); - - b.ToTable("tenant_quota_usages", null, t => - { - t.HasComment("租户配额使用情况快照。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantReviewClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ClaimedAt") - .HasColumnType("timestamp with time zone") - .HasComment("领取时间(UTC)。"); - - b.Property("ClaimedBy") - .HasColumnType("bigint") - .HasComment("领取人用户 ID。"); - - b.Property("ClaimedByName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("领取人名称(展示用快照)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReleasedAt") - .HasColumnType("timestamp with time zone") - .HasComment("释放时间(UTC),未释放时为 null。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("被领取的租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("ClaimedBy"); - - b.HasIndex("TenantId") - .IsUnique() - .HasFilter("\"ReleasedAt\" IS NULL AND \"DeletedAt\" IS NULL"); - - b.ToTable("tenant_review_claims", null, t => - { - t.HasComment("租户入驻审核领取记录(防止多管理员并发审核)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscription", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AutoRenew") - .HasColumnType("boolean") - .HasComment("是否开启自动续费。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("订阅生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("订阅到期时间(UTC)。"); - - b.Property("NextBillingDate") - .HasColumnType("timestamp with time zone") - .HasComment("下一个计费时间,配合自动续费使用。"); - - b.Property("Notes") - .HasColumnType("text") - .HasComment("运营备注信息。"); - - b.Property("ScheduledPackageId") - .HasColumnType("bigint") - .HasComment("若已排期升降配,对应的新套餐 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("订阅当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TenantPackageId") - .HasColumnType("bigint") - .HasComment("当前订阅关联的套餐标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantPackageId"); - - b.ToTable("tenant_subscriptions", null, t => - { - t.HasComment("租户套餐订阅记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscriptionHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasColumnType("numeric") - .HasComment("相关费用。"); - - b.Property("ChangeType") - .HasColumnType("integer") - .HasComment("变更类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Currency") - .HasMaxLength(8) - .HasColumnType("character varying(8)") - .HasComment("币种。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("FromPackageId") - .HasColumnType("bigint") - .HasComment("原套餐 ID。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("租户标识。"); - - b.Property("TenantSubscriptionId") - .HasColumnType("bigint") - .HasComment("对应的订阅 ID。"); - - b.Property("ToPackageId") - .HasColumnType("bigint") - .HasComment("新套餐 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantSubscriptionId"); - - b.ToTable("tenant_subscription_histories", null, t => - { - t.HasComment("租户套餐订阅变更记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantVerificationProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdditionalDataJson") - .HasColumnType("text") - .HasComment("附加资料(JSON)。"); - - b.Property("BankAccountName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("开户名。"); - - b.Property("BankAccountNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("银行账号。"); - - b.Property("BankName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("银行名称。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照编号。"); - - b.Property("BusinessLicenseUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营业执照文件地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LegalPersonIdBackUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证反面。"); - - b.Property("LegalPersonIdFrontUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证正面。"); - - b.Property("LegalPersonIdNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("法人身份证号。"); - - b.Property("LegalPersonName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人姓名。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注。"); - - b.Property("ReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核时间。"); - - b.Property("ReviewedBy") - .HasColumnType("bigint") - .HasComment("审核人 ID。"); - - b.Property("ReviewedByName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("审核人姓名。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("实名状态。"); - - b.Property("SubmittedAt") - .HasColumnType("timestamp with time zone") - .HasComment("提交时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("对应的租户标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId") - .IsUnique(); - - b.ToTable("tenant_verification_profiles", null, t => - { - t.HasComment("租户实名认证资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.HasOne("TakeoutSaaS.Domain.Orders.Entities.Order", null) - .WithMany() - .HasForeignKey("OrderId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215143054_AddTenantPackageRecommendationAndTags.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215143054_AddTenantPackageRecommendationAndTags.cs deleted file mode 100644 index ef0c6c2..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251215143054_AddTenantPackageRecommendationAndTags.cs +++ /dev/null @@ -1,42 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - /// - public partial class AddTenantPackageRecommendationAndTags : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "IsRecommended", - table: "tenant_packages", - type: "boolean", - nullable: false, - defaultValue: false, - comment: "是否推荐展示(运营推荐标识)。"); - - migrationBuilder.AddColumn( - name: "Tags", - table: "tenant_packages", - type: "text[]", - nullable: false, - defaultValue: new string[0], - comment: "套餐标签(用于展示与对比页)。"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "IsRecommended", - table: "tenant_packages"); - - migrationBuilder.DropColumn( - name: "Tags", - table: "tenant_packages"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251217092209_AddQuotaPackagesAndPayments.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251217092209_AddQuotaPackagesAndPayments.Designer.cs deleted file mode 100644 index 7d2d1ea..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251217092209_AddQuotaPackagesAndPayments.Designer.cs +++ /dev/null @@ -1,7101 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.App.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - [DbContext(typeof(TakeoutAppDbContext))] - [Migration("20251217092209_AddQuotaPackagesAndPayments")] - partial class AddQuotaPackagesAndPayments - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricAlertRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionJson") - .IsRequired() - .HasColumnType("text") - .HasComment("触发条件 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Enabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("关联指标。"); - - b.Property("NotificationChannels") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("通知渠道。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("告警级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "Severity"); - - b.ToTable("metric_alert_rules", null, t => - { - t.HasComment("指标告警规则。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricDefinition", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("指标编码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultAggregation") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("默认聚合方式。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("说明。"); - - b.Property("DimensionsJson") - .HasColumnType("text") - .HasComment("维度描述 JSON。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("指标名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("metric_definitions", null, t => - { - t.HasComment("指标定义,描述可观测的数据点。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricSnapshot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DimensionKey") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("维度键(JSON)。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("指标定义 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Value") - .HasPrecision(18, 4) - .HasColumnType("numeric(18,4)") - .HasComment("数值。"); - - b.Property("WindowEnd") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口结束。"); - - b.Property("WindowStart") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口开始。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "DimensionKey", "WindowStart", "WindowEnd") - .IsUnique(); - - b.ToTable("metric_snapshots", null, t => - { - t.HasComment("指标快照,用于大盘展示。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.Coupon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("券码或序列号。"); - - b.Property("CouponTemplateId") - .HasColumnType("bigint") - .HasComment("模板标识。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("发放时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID(已使用时记录)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedAt") - .HasColumnType("timestamp with time zone") - .HasComment("使用时间。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("归属用户。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("coupons", null, t => - { - t.HasComment("用户领取的券。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.CouponTemplate", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowStack") - .HasColumnType("boolean") - .HasComment("是否允许叠加其他优惠。"); - - b.Property("ChannelsJson") - .HasColumnType("text") - .HasComment("发放渠道(JSON)。"); - - b.Property("ClaimedQuantity") - .HasColumnType("integer") - .HasComment("已领取数量。"); - - b.Property("CouponType") - .HasColumnType("integer") - .HasComment("券类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("DiscountCap") - .HasColumnType("numeric") - .HasComment("折扣上限(针对折扣券)。"); - - b.Property("MinimumSpend") - .HasColumnType("numeric") - .HasComment("最低消费门槛。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("模板名称。"); - - b.Property("ProductScopeJson") - .HasColumnType("text") - .HasComment("适用品类或商品范围(JSON)。"); - - b.Property("RelativeValidDays") - .HasColumnType("integer") - .HasComment("有效天数(相对发放时间)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreScopeJson") - .HasColumnType("text") - .HasComment("适用门店 ID 集合(JSON)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TotalQuantity") - .HasColumnType("integer") - .HasComment("总发放数量上限。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ValidFrom") - .HasColumnType("timestamp with time zone") - .HasComment("可用开始时间。"); - - b.Property("ValidTo") - .HasColumnType("timestamp with time zone") - .HasComment("可用结束时间。"); - - b.Property("Value") - .HasColumnType("numeric") - .HasComment("面值或折扣额度。"); - - b.HasKey("Id"); - - b.ToTable("coupon_templates", null, t => - { - t.HasComment("优惠券模板。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.PromotionCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AudienceDescription") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("目标人群描述。"); - - b.Property("BannerUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营销素材(如 banner)。"); - - b.Property("Budget") - .HasColumnType("numeric") - .HasComment("预算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("PromotionType") - .HasColumnType("integer") - .HasComment("活动类型。"); - - b.Property("RulesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("活动规则 JSON。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("活动状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("promotion_campaigns", null, t => - { - t.HasComment("营销活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChatSessionId") - .HasColumnType("bigint") - .HasComment("会话标识。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("消息内容。"); - - b.Property("ContentType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("消息类型(文字/图片/语音等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRead") - .HasColumnType("boolean") - .HasComment("是否已读。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("读取时间。"); - - b.Property("SenderType") - .HasColumnType("integer") - .HasComment("发送方类型。"); - - b.Property("SenderUserId") - .HasColumnType("bigint") - .HasComment("发送方用户 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ChatSessionId", "CreatedAt"); - - b.ToTable("chat_messages", null, t => - { - t.HasComment("会话消息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AgentUserId") - .HasColumnType("bigint") - .HasComment("当前客服员工 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("顾客用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndedAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("IsBotActive") - .HasColumnType("boolean") - .HasComment("是否机器人接待中。"); - - b.Property("SessionCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话编号。"); - - b.Property("StartedAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店(可空为平台)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionCode") - .IsUnique(); - - b.ToTable("chat_sessions", null, t => - { - t.HasComment("客服会话。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.SupportTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AssignedAgentId") - .HasColumnType("bigint") - .HasComment("指派的客服。"); - - b.Property("ClosedAt") - .HasColumnType("timestamp with time zone") - .HasComment("关闭时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("客户用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .IsRequired() - .HasColumnType("text") - .HasComment("工单详情。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单(如有)。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("优先级。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("Subject") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("工单主题。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("工单编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TicketNo") - .IsUnique(); - - b.ToTable("support_tickets", null, t => - { - t.HasComment("客服工单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.TicketComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttachmentsJson") - .HasColumnType("text") - .HasComment("附件 JSON。"); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人 ID。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsInternal") - .HasColumnType("boolean") - .HasComment("是否内部备注。"); - - b.Property("SupportTicketId") - .HasColumnType("bigint") - .HasComment("工单标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SupportTicketId"); - - b.ToTable("ticket_comments", null, t => - { - t.HasComment("工单评论/流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryEvent", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryOrderId") - .HasColumnType("bigint") - .HasComment("配送单标识。"); - - b.Property("EventType") - .HasColumnType("integer") - .HasComment("事件类型。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("事件描述。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始数据 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DeliveryOrderId", "EventType"); - - b.ToTable("delivery_events", null, t => - { - t.HasComment("配送状态事件流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CourierName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("骑手姓名。"); - - b.Property("CourierPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("骑手电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveredAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("DispatchedAt") - .HasColumnType("timestamp with time zone") - .HasComment("下发时间。"); - - b.Property("FailureReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("异常原因。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("获取或设置关联订单 ID。"); - - b.Property("PickedUpAt") - .HasColumnType("timestamp with time zone") - .HasComment("取餐时间。"); - - b.Property("Provider") - .HasColumnType("integer") - .HasComment("配送服务商。"); - - b.Property("ProviderOrderId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方配送单号。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId") - .IsUnique(); - - b.ToTable("delivery_orders", null, t => - { - t.HasComment("配送单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliateOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("推广人标识。"); - - b.Property("BuyerUserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedCommission") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("预计佣金。"); - - b.Property("OrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("订单金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("SettledAt") - .HasColumnType("timestamp with time zone") - .HasComment("结算完成时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "OrderId") - .IsUnique(); - - b.ToTable("affiliate_orders", null, t => - { - t.HasComment("分销订单记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePartner", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChannelType") - .HasColumnType("integer") - .HasComment("渠道类型。"); - - b.Property("CommissionRate") - .HasColumnType("numeric") - .HasComment("分成比例(0-1)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称或渠道名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID(如绑定平台账号)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DisplayName"); - - b.ToTable("affiliate_partners", null, t => - { - t.HasComment("分销/推广合作伙伴。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePayout", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("合作伙伴标识。"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("结算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("打款时间。"); - - b.Property("Period") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("结算周期描述。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "Period") - .IsUnique(); - - b.ToTable("affiliate_payouts", null, t => - { - t.HasComment("佣金结算记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowMakeupCount") - .HasColumnType("integer") - .HasComment("支持补签次数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("活动描述。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("结束日期。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("RewardsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("连签奖励 JSON。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("开始日期。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name"); - - b.ToTable("checkin_campaigns", null, t => - { - t.HasComment("签到活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CheckInCampaignId") - .HasColumnType("bigint") - .HasComment("活动标识。"); - - b.Property("CheckInDate") - .HasColumnType("timestamp with time zone") - .HasComment("签到日期(本地)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsMakeup") - .HasColumnType("boolean") - .HasComment("是否补签。"); - - b.Property("RewardJson") - .IsRequired() - .HasColumnType("text") - .HasComment("获得奖励 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "CheckInCampaignId", "UserId", "CheckInDate") - .IsUnique(); - - b.ToTable("checkin_records", null, t => - { - t.HasComment("用户签到记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsDeleted") - .HasColumnType("boolean") - .HasComment("状态。"); - - b.Property("ParentId") - .HasColumnType("bigint") - .HasComment("父级评论 ID。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "CreatedAt"); - - b.ToTable("community_comments", null, t => - { - t.HasComment("社区评论。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityPost", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("作者用户 ID。"); - - b.Property("CommentCount") - .HasColumnType("integer") - .HasComment("评论数。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LikeCount") - .HasColumnType("integer") - .HasComment("点赞数。"); - - b.Property("MediaJson") - .HasColumnType("text") - .HasComment("媒体资源 JSON。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AuthorUserId", "CreatedAt"); - - b.ToTable("community_posts", null, t => - { - t.HasComment("社区动态。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityReaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态 ID。"); - - b.Property("ReactedAt") - .HasColumnType("timestamp with time zone") - .HasComment("时间戳。"); - - b.Property("ReactionType") - .HasColumnType("integer") - .HasComment("反应类型。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "UserId") - .IsUnique(); - - b.ToTable("community_reactions", null, t => - { - t.HasComment("社区互动反馈。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentCount") - .HasColumnType("integer") - .HasComment("当前已参与人数。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("GroupOrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("拼单编号。"); - - b.Property("GroupPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("拼团价格。"); - - b.Property("LeaderUserId") - .HasColumnType("bigint") - .HasComment("团长用户 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("关联商品或套餐。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("拼团状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("SucceededAt") - .HasColumnType("timestamp with time zone") - .HasComment("成团时间。"); - - b.Property("TargetCount") - .HasColumnType("integer") - .HasComment("成团需要的人数。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderNo") - .IsUnique(); - - b.ToTable("group_orders", null, t => - { - t.HasComment("拼单活动。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupParticipant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GroupOrderId") - .HasColumnType("bigint") - .HasComment("拼单活动标识。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("参与时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("对应订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("参与状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderId", "UserId") - .IsUnique(); - - b.ToTable("group_participants", null, t => - { - t.HasComment("拼单参与者。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryAdjustment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdjustmentType") - .HasColumnType("integer") - .HasComment("调整类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("InventoryItemId") - .HasColumnType("bigint") - .HasComment("对应的库存记录标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("调整数量,正数增加,负数减少。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("原因说明。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "InventoryItemId", "OccurredAt"); - - b.ToTable("inventory_adjustments", null, t => - { - t.HasComment("库存调整记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryBatch", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("ProductionDate") - .HasColumnType("timestamp with time zone") - .HasComment("生产日期。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("入库数量。"); - - b.Property("RemainingQuantity") - .HasColumnType("integer") - .HasComment("剩余数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber") - .IsUnique(); - - b.ToTable("inventory_batches", null, t => - { - t.HasComment("SKU 批次信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchConsumeStrategy") - .HasColumnType("integer") - .HasComment("批次扣减策略。"); - - b.Property("BatchNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号,可为空表示混批。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售商品。"); - - b.Property("IsSoldOut") - .HasColumnType("boolean") - .HasComment("是否标记售罄。"); - - b.Property("Location") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("储位或仓位信息。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单品限购(覆盖商品级 MaxQuantityPerOrder)。"); - - b.Property("PresaleCapacity") - .HasColumnType("integer") - .HasComment("预售名额(上限)。"); - - b.Property("PresaleEndTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售结束时间(UTC)。"); - - b.Property("PresaleLocked") - .HasColumnType("integer") - .HasComment("当前预售已锁定数量。"); - - b.Property("PresaleStartTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售开始时间(UTC)。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("QuantityOnHand") - .HasColumnType("integer") - .HasComment("可用库存。"); - - b.Property("QuantityReserved") - .HasColumnType("integer") - .HasComment("已锁定库存(订单占用)。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("SafetyStock") - .HasColumnType("integer") - .HasComment("安全库存阈值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber"); - - b.ToTable("inventory_items", null, t => - { - t.HasComment("SKU 在门店的库存信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryLockRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("IdempotencyKey") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("幂等键。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售锁定。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU ID。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("锁定数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("锁定状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "IdempotencyKey") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "Status"); - - b.ToTable("inventory_lock_records", null, t => - { - t.HasComment("库存锁定记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberGrowthLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChangeValue") - .HasColumnType("integer") - .HasComment("变动数量。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentValue") - .HasColumnType("integer") - .HasComment("当前成长值。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_growth_logs", null, t => - { - t.HasComment("成长值变动日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberPointLedger", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BalanceAfterChange") - .HasColumnType("integer") - .HasComment("变动后余额。"); - - b.Property("ChangeAmount") - .HasColumnType("integer") - .HasComment("变动数量,可为负值。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(如适用)。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Reason") - .HasColumnType("integer") - .HasComment("变动原因。"); - - b.Property("SourceId") - .HasColumnType("bigint") - .HasComment("来源 ID(订单、活动等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_point_ledgers", null, t => - { - t.HasComment("积分变动流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AvatarUrl") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像。"); - - b.Property("BirthDate") - .HasColumnType("timestamp with time zone") - .HasComment("生日。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GrowthValue") - .HasColumnType("integer") - .HasComment("成长值/经验值。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("注册时间。"); - - b.Property("MemberTierId") - .HasColumnType("bigint") - .HasComment("当前会员等级 ID。"); - - b.Property("Mobile") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("Nickname") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称。"); - - b.Property("PointsBalance") - .HasColumnType("integer") - .HasComment("会员积分余额。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会员状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Mobile") - .IsUnique(); - - b.ToTable("member_profiles", null, t => - { - t.HasComment("会员档案。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberTier", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BenefitsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("等级权益(JSON)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("等级名称。"); - - b.Property("RequiredGrowth") - .HasColumnType("integer") - .HasComment("所需成长值。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("member_tiers", null, t => - { - t.HasComment("会员等级定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.Merchant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("BrandAlias") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("品牌简称或别名。"); - - b.Property("BrandName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("品牌名称(对外展示)。"); - - b.Property("BusinessLicenseImageUrl") - .HasColumnType("text") - .HasComment("营业执照扫描件地址。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照号。"); - - b.Property("Category") - .HasColumnType("text") - .HasComment("品牌所属品类,如火锅、咖啡等。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("联系邮箱。"); - - b.Property("ContactPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在区县。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("入驻时间。"); - - b.Property("LastReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次审核时间。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度信息。"); - - b.Property("LegalPerson") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人或负责人姓名。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("品牌 Logo。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度信息。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注或驳回原因。"); - - b.Property("ServicePhone") - .HasColumnType("text") - .HasComment("客服电话。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("入驻状态。"); - - b.Property("SupportEmail") - .HasColumnType("text") - .HasComment("客服邮箱。"); - - b.Property("TaxNumber") - .HasColumnType("text") - .HasComment("税号/统一社会信用代码。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.ToTable("merchants", null, t => - { - t.HasComment("商户主体信息,承载入驻和资质审核结果。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantAuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("动作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("详情描述。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("商户标识。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId"); - - b.ToTable("merchant_audit_logs", null, t => - { - t.HasComment("商户入驻审核日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("显示顺序,越小越靠前。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否可用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("类目名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("merchant_categories", null, t => - { - t.HasComment("商户可选类目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantContract", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ContractNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("合同编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同结束时间。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("合同文件存储地址。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("SignedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签署时间。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("合同状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TerminatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("终止时间。"); - - b.Property("TerminationReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("终止原因。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "ContractNumber") - .IsUnique(); - - b.ToTable("merchant_contracts", null, t => - { - t.HasComment("商户合同记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantDocument", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DocumentNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("证照编号。"); - - b.Property("DocumentType") - .HasColumnType("integer") - .HasComment("证照类型。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期日期。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("证照文件链接。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签发日期。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Remarks") - .HasColumnType("text") - .HasComment("审核备注或驳回原因。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("审核状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "DocumentType"); - - b.ToTable("merchant_documents", null, t => - { - t.HasComment("商户提交的资质或证照材料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantStaff", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Email") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("邮箱地址。"); - - b.Property("IdentityUserId") - .HasColumnType("bigint") - .HasComment("登录账号 ID(指向统一身份体系)。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("员工姓名。"); - - b.Property("PermissionsJson") - .HasColumnType("text") - .HasComment("自定义权限(JSON)。"); - - b.Property("Phone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("员工角色类型。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("员工状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("可选的关联门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "Phone"); - - b.ToTable("merchant_staff", null, t => - { - t.HasComment("商户员工账号,支持门店维度分配。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.MapLocation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Landmark") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("打车/导航落点描述。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("名称。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店 ID,可空表示独立 POI。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("map_locations", null, t => - { - t.HasComment("地图 POI 信息,用于门店定位和推荐。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.NavigationRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("来源通道(小程序、H5 等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("请求时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TargetApp") - .HasColumnType("integer") - .HasComment("跳转的地图应用。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId", "RequestedAt"); - - b.ToTable("navigation_requests", null, t => - { - t.HasComment("用户发起的导航请求日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("扩展 JSON(规格、加料选项等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品或 SKU 标识。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称快照。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("自定义备注(口味要求)。"); - - b.Property("ShoppingCartId") - .HasColumnType("bigint") - .HasComment("所属购物车标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价快照。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ShoppingCartId"); - - b.ToTable("cart_items", null, t => - { - t.HasComment("购物车条目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItemAddon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CartItemId") - .HasColumnType("bigint") - .HasComment("所属购物车条目。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("OptionId") - .HasColumnType("bigint") - .HasComment("选项 ID(可对应 ProductAddonOption)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("cart_item_addons", null, t => - { - t.HasComment("购物车条目的加料/附加项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CheckoutSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("SessionToken") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话 Token。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.Property("ValidationResultJson") - .IsRequired() - .HasColumnType("text") - .HasComment("校验结果明细 JSON。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionToken") - .IsUnique(); - - b.ToTable("checkout_sessions", null, t => - { - t.HasComment("结账会话,记录校验上下文。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.ShoppingCart", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryPreference") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("履约方式(堂食/自提/配送)缓存。"); - - b.Property("LastModifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次修改时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("购物车状态,包含正常/锁定。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableContext") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌码或场景标识(扫码点餐)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId") - .IsUnique(); - - b.ToTable("shopping_carts", null, t => - { - t.HasComment("用户购物车,按租户/门店隔离。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.Order", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("取消原因。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("下单渠道。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("顾客姓名。"); - - b.Property("CustomerPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("顾客手机号。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryType") - .HasColumnType("integer") - .HasComment("履约类型。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("优惠金额。"); - - b.Property("FinishedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("ItemsAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("商品总额。"); - - b.Property("OrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("订单号。"); - - b.Property("PaidAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付时间。"); - - b.Property("PayableAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额。"); - - b.Property("PaymentStatus") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("QueueNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队号(如有)。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationId") - .HasColumnType("bigint") - .HasComment("预约 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TableNo") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("就餐桌号。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "Status"); - - b.ToTable("orders", null, t => - { - t.HasComment("交易订单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("自定义属性 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("折扣金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品 ID。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("SkuName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("SKU/规格描述。"); - - b.Property("SubTotal") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("小计。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("单位。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("OrderId"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("order_items", null, t => - { - t.HasComment("订单明细。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderStatusHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注信息。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识(可为空表示系统)。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("变更后的状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId", "OccurredAt"); - - b.ToTable("order_status_histories", null, t => - { - t.HasComment("订单状态流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.RefundRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("申请金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("ProcessedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核完成时间。"); - - b.Property("Reason") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("申请原因。"); - - b.Property("RefundNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("退款单号。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("用户提交时间。"); - - b.Property("ReviewNotes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "RefundNo") - .IsUnique(); - - b.ToTable("refund_requests", null, t => - { - t.HasComment("售后/退款申请。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("支付金额。"); - - b.Property("ChannelTransactionId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方渠道单号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Method") - .HasColumnType("integer") - .HasComment("支付方式。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付完成时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始回调内容。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("错误/备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TradeNo") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("平台交易号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("payment_records", null, t => - { - t.HasComment("支付流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRefundRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("退款金额。"); - - b.Property("ChannelRefundId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("渠道退款流水号。"); - - b.Property("CompletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("渠道返回的原始数据 JSON。"); - - b.Property("PaymentRecordId") - .HasColumnType("bigint") - .HasComment("原支付记录标识。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("退款请求时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PaymentRecordId"); - - b.ToTable("payment_refund_records", null, t => - { - t.HasComment("支付渠道退款流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.Product", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CategoryId") - .HasColumnType("bigint") - .HasComment("所属分类。"); - - b.Property("CoverImage") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("主图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("商品描述。"); - - b.Property("EnableDelivery") - .HasColumnType("boolean") - .HasComment("支持配送。"); - - b.Property("EnableDineIn") - .HasColumnType("boolean") - .HasComment("支持堂食。"); - - b.Property("EnablePickup") - .HasColumnType("boolean") - .HasComment("支持自提。"); - - b.Property("GalleryImages") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Gallery 图片逗号分隔。"); - - b.Property("IsFeatured") - .HasColumnType("boolean") - .HasComment("是否热门推荐。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("最大每单限购。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("现价。"); - - b.Property("SpuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("商品编码。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("商品状态。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("库存数量(可选)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("Subtitle") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("副标题/卖点。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("售卖单位(份/杯等)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SpuCode") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("products", null, t => - { - t.HasComment("商品(SPU)信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("MaxSelect") - .HasColumnType("integer") - .HasComment("最大选择数量。"); - - b.Property("MinSelect") - .HasColumnType("integer") - .HasComment("最小选择数量。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "Name"); - - b.ToTable("product_addon_groups", null, t => - { - t.HasComment("加料/做法分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AddonGroupId") - .HasColumnType("bigint") - .HasComment("所属加料分组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选项。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("product_addon_options", null, t => - { - t.HasComment("加料选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称,例如“辣度”“份量”。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型(单选/多选)。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("显示排序。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店,可为空表示所有门店共享。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("product_attribute_groups", null, t => - { - t.HasComment("商品规格/属性分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributeGroupId") - .HasColumnType("bigint") - .HasComment("所属规格组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选中。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AttributeGroupId", "Name") - .IsUnique(); - - b.ToTable("product_attribute_options", null, t => - { - t.HasComment("商品规格选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("分类描述。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分类名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("product_categories", null, t => - { - t.HasComment("商品分类。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductMediaAsset", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Caption") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述或标题。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MediaType") - .HasColumnType("integer") - .HasComment("媒体类型。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品标识。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Url") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("媒资链接。"); - - b.HasKey("Id"); - - b.ToTable("product_media_assets", null, t => - { - t.HasComment("商品媒资素材。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductPricingRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("条件描述(JSON),如会员等级、渠道等。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效结束时间。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("特殊价格。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("RuleType") - .HasColumnType("integer") - .HasComment("策略类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StartTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效开始时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("WeekdaysJson") - .HasColumnType("text") - .HasComment("生效星期(JSON 数组)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "RuleType"); - - b.ToTable("product_pricing_rules", null, t => - { - t.HasComment("商品价格策略,支持会员价/时段价等。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductSku", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("规格属性 JSON(记录选项 ID)。"); - - b.Property("Barcode") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("条形码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("售价。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SkuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("SKU 编码。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("可售库存。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weight") - .HasPrecision(10, 3) - .HasColumnType("numeric(10,3)") - .HasComment("重量(千克)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SkuCode") - .IsUnique(); - - b.ToTable("product_skus", null, t => - { - t.HasComment("商品 SKU,记录具体规格组合价格。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Queues.Entities.QueueTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CalledAt") - .HasColumnType("timestamp with time zone") - .HasComment("叫号时间。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedWaitMinutes") - .HasColumnType("integer") - .HasComment("预计等待分钟。"); - - b.Property("ExpiredAt") - .HasColumnType("timestamp with time zone") - .HasComment("过号时间。"); - - b.Property("PartySize") - .HasColumnType("integer") - .HasComment("就餐人数。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("获取或设置所属门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNumber") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.HasIndex("TenantId", "StoreId", "TicketNumber") - .IsUnique(); - - b.ToTable("queue_tickets", null, t => - { - t.HasComment("排队叫号。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Reservations.Entities.Reservation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CheckInCode") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("核销码/到店码。"); - - b.Property("CheckedInAt") - .HasColumnType("timestamp with time zone") - .HasComment("实际签到时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("客户姓名。"); - - b.Property("CustomerPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PeopleCount") - .HasColumnType("integer") - .HasComment("用餐人数。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("预约号。"); - - b.Property("ReservationTime") - .HasColumnType("timestamp with time zone") - .HasComment("预约时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TablePreference") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌型/标签。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ReservationNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("reservations", null, t => - { - t.HasComment("预约/预订记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.Store", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("Announcement") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("门店公告。"); - - b.Property("BusinessHours") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("门店营业时段描述(备用字符串)。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("门店编码,便于扫码及外部对接。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家或地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("门店海报。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryRadiusKm") - .HasPrecision(6, 2) - .HasColumnType("numeric(6,2)") - .HasComment("默认配送半径(公里)。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("门店描述或公告。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区县信息。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("高德/腾讯地图经度。"); - - b.Property("ManagerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("门店负责人姓名。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("门店名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("门店当前运营状态。"); - - b.Property("SupportsDelivery") - .HasColumnType("boolean") - .HasComment("是否支持配送。"); - - b.Property("SupportsDineIn") - .HasColumnType("boolean") - .HasComment("是否支持堂食。"); - - b.Property("SupportsPickup") - .HasColumnType("boolean") - .HasComment("是否支持自提。"); - - b.Property("SupportsQueueing") - .HasColumnType("boolean") - .HasComment("支持排队叫号。"); - - b.Property("SupportsReservation") - .HasColumnType("boolean") - .HasComment("支持预约。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("门店标签(逗号分隔)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.HasIndex("TenantId", "MerchantId"); - - b.ToTable("stores", null, t => - { - t.HasComment("门店信息,承载营业配置与能力。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreBusinessHour", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CapacityLimit") - .HasColumnType("integer") - .HasComment("最大接待容量或单量限制。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DayOfWeek") - .HasColumnType("integer") - .HasComment("星期几,0 表示周日。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间(本地时间)。"); - - b.Property("HourType") - .HasColumnType("integer") - .HasComment("时段类型(正常营业、休息、预约等)。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间(本地时间)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "DayOfWeek"); - - b.ToTable("store_business_hours", null, t => - { - t.HasComment("门店营业时段配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreDeliveryZone", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("EstimatedMinutes") - .HasColumnType("integer") - .HasComment("预计送达分钟。"); - - b.Property("MinimumOrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("起送价。"); - - b.Property("PolygonGeoJson") - .IsRequired() - .HasColumnType("text") - .HasComment("GeoJSON 表示的多边形范围。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ZoneName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ZoneName"); - - b.ToTable("store_delivery_zones", null, t => - { - t.HasComment("门店配送范围配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreEmployeeShift", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("排班角色。"); - - b.Property("ShiftDate") - .HasColumnType("timestamp with time zone") - .HasComment("班次日期。"); - - b.Property("StaffId") - .HasColumnType("bigint") - .HasComment("员工标识。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ShiftDate", "StaffId") - .IsUnique(); - - b.ToTable("store_employee_shifts", null, t => - { - t.HasComment("门店员工排班记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreHoliday", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Date") - .HasColumnType("timestamp with time zone") - .HasComment("日期。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsClosed") - .HasColumnType("boolean") - .HasComment("是否全天闭店。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("说明内容。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Date") - .IsUnique(); - - b.ToTable("store_holidays", null, t => - { - t.HasComment("门店休息日或特殊营业日。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSetting", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowDaysAhead") - .HasColumnType("integer") - .HasComment("可预约天数(含当天)。"); - - b.Property("AllowToday") - .HasColumnType("boolean") - .HasComment("是否允许当天自提。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultCutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("默认截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单笔自提最大份数。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId") - .IsUnique(); - - b.ToTable("store_pickup_settings", null, t => - { - t.HasComment("门店自提配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSlot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("容量(份数)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("当天结束时间(UTC)。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("档期名称。"); - - b.Property("ReservedCount") - .HasColumnType("integer") - .HasComment("已占用数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("当天开始时间(UTC)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weekdays") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("适用星期(逗号分隔 1-7)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("store_pickup_slots", null, t => - { - t.HasComment("门店自提档期。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTable", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AreaId") - .HasColumnType("bigint") - .HasComment("所在区域 ID。"); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("可容纳人数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("QrCodeUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("桌码二维码地址。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前桌台状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("桌码。"); - - b.Property("Tags") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("桌台标签(堂食、快餐等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "TableCode") - .IsUnique(); - - b.ToTable("store_tables", null, t => - { - t.HasComment("桌台信息与二维码绑定。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTableArea", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("区域描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name") - .IsUnique(); - - b.ToTable("store_table_areas", null, t => - { - t.HasComment("门店桌台区域配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.OperationLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OperationType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作类型:BatchExtend, BatchRemind, StatusChange 等。"); - - b.Property("OperatorId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人ID。"); - - b.Property("OperatorName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("操作人名称。"); - - b.Property("Parameters") - .HasColumnType("text") - .HasComment("操作参数(JSON)。"); - - b.Property("Result") - .HasColumnType("text") - .HasComment("操作结果(JSON)。"); - - b.Property("Success") - .HasColumnType("boolean") - .HasComment("是否成功。"); - - b.Property("TargetIds") - .HasColumnType("text") - .HasComment("目标ID列表(JSON)。"); - - b.Property("TargetType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("目标类型:Subscription, Bill 等。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("CreatedAt"); - - b.HasIndex("OperationType", "CreatedAt"); - - b.ToTable("operation_logs", null, t => - { - t.HasComment("运营操作日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.QuotaPackage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("描述。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否上架。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("配额包名称。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("价格。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型。"); - - b.Property("QuotaValue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配额数值。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("排序。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("QuotaType", "IsActive", "SortOrder"); - - b.ToTable("quota_packages", null, t => - { - t.HasComment("配额包定义(平台提供的可购买配额包)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.Tenant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("text") - .HasComment("详细地址信息。"); - - b.Property("City") - .HasColumnType("text") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("租户短编码,作为跨系统引用的唯一标识。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("主联系人邮箱。"); - - b.Property("ContactName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("主联系人姓名。"); - - b.Property("ContactPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("主联系人电话。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家/地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("品牌海报或封面图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("服务生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("服务到期时间(UTC)。"); - - b.Property("Industry") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所属行业,如餐饮、零售等。"); - - b.Property("LegalEntityName") - .HasColumnType("text") - .HasComment("法人或公司主体名称。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("LOGO 图片地址。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("租户全称或品牌名称。"); - - b.Property("PrimaryOwnerUserId") - .HasColumnType("bigint") - .HasComment("系统内对应的租户所有者账号 ID。"); - - b.Property("Province") - .HasColumnType("text") - .HasComment("所在省份或州。"); - - b.Property("Remarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息,用于运营记录特殊说明。"); - - b.Property("ShortName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("对外展示的简称。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("租户当前状态,涵盖审核、启用、停用等场景。"); - - b.Property("SuspendedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次暂停服务时间。"); - - b.Property("SuspensionReason") - .HasColumnType("text") - .HasComment("暂停或终止的原因说明。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("业务标签集合(逗号分隔)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Website") - .HasColumnType("text") - .HasComment("官网或主要宣传链接。"); - - b.HasKey("Id"); - - b.HasIndex("Code") - .IsUnique(); - - b.HasIndex("ContactPhone") - .IsUnique(); - - b.ToTable("tenants", null, t => - { - t.HasComment("平台租户信息,描述租户的生命周期与基础资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementType") - .HasColumnType("integer") - .HasComment("公告类型。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("公告正文(可为 Markdown/HTML,前端自行渲染)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("失效时间(UTC),为空表示长期有效。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("展示优先级,数值越大越靠前。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("公告标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AnnouncementType", "IsActive"); - - b.HasIndex("TenantId", "EffectiveFrom", "EffectiveTo"); - - b.ToTable("tenant_announcements", null, t => - { - t.HasComment("租户公告。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncementRead", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementId") - .HasColumnType("bigint") - .HasComment("公告 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("已读时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("已读用户 ID(后台账号),为空表示租户级已读。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AnnouncementId", "UserId") - .IsUnique(); - - b.ToTable("tenant_announcement_reads", null, t => - { - t.HasComment("租户公告已读记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("操作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentStatus") - .HasColumnType("integer") - .HasComment("新状态。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("详细描述。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人名称。"); - - b.Property("PreviousStatus") - .HasColumnType("integer") - .HasComment("原状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("关联的租户标识。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("日志标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.ToTable("tenant_audit_logs", null, t => - { - t.HasComment("租户运营审核日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantBillingStatement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AmountDue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额。"); - - b.Property("AmountPaid") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DueDate") - .HasColumnType("timestamp with time zone") - .HasComment("到期日。"); - - b.Property("LineItemsJson") - .HasColumnType("text") - .HasComment("账单明细 JSON,记录各项费用。"); - - b.Property("PeriodEnd") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期结束时间。"); - - b.Property("PeriodStart") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期开始时间。"); - - b.Property("StatementNo") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("账单编号,供对账查询。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前付款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StatementNo") - .IsUnique(); - - b.ToTable("tenant_billing_statements", null, t => - { - t.HasComment("租户账单,用于呈现周期性收费。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantNotification", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("发布通道(站内、邮件、短信等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("通知正文。"); - - b.Property("MetadataJson") - .HasColumnType("text") - .HasComment("附加元数据 JSON。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("租户是否已阅读。"); - - b.Property("SentAt") - .HasColumnType("timestamp with time zone") - .HasComment("推送时间。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("通知重要级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("通知标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Channel", "SentAt"); - - b.ToTable("tenant_notifications", null, t => - { - t.HasComment("面向租户的站内通知或消息推送。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantPackage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("套餐描述,包含适用场景、权益等。"); - - b.Property("FeaturePoliciesJson") - .HasColumnType("text") - .HasComment("权益明细 JSON,记录自定义特性开关。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否仍启用(平台控制)。"); - - b.Property("IsAllowNewTenantPurchase") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否允许新租户购买/选择(仅影响新购)。"); - - b.Property("IsPublicVisible") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否对外可见(展示页/套餐列表可见性)。"); - - b.Property("IsRecommended") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false) - .HasComment("是否推荐展示(运营推荐标识)。"); - - b.Property("MaxAccountCount") - .HasColumnType("integer") - .HasComment("允许创建的最大账号数。"); - - b.Property("MaxDeliveryOrders") - .HasColumnType("integer") - .HasComment("每月可调用的配送单数量上限。"); - - b.Property("MaxSmsCredits") - .HasColumnType("integer") - .HasComment("每月短信额度上限。"); - - b.Property("MaxStorageGb") - .HasColumnType("integer") - .HasComment("存储容量上限(GB)。"); - - b.Property("MaxStoreCount") - .HasColumnType("integer") - .HasComment("允许的最大门店数。"); - - b.Property("MonthlyPrice") - .HasColumnType("numeric") - .HasComment("月付价格,单位:人民币元。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("套餐名称,展示给租户的简称。"); - - b.Property("PackageType") - .HasColumnType("integer") - .HasComment("套餐分类(试用、标准、旗舰等)。"); - - b.Property("PublishStatus") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("发布状态:0=草稿,1=已发布。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("展示排序,数值越小越靠前。"); - - b.PrimitiveCollection("Tags") - .IsRequired() - .HasColumnType("text[]") - .HasComment("套餐标签(用于展示与对比页)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("YearlyPrice") - .HasColumnType("numeric") - .HasComment("年付价格,单位:人民币元。"); - - b.HasKey("Id"); - - b.HasIndex("IsActive", "SortOrder"); - - b.HasIndex("PublishStatus", "IsActive", "IsPublicVisible", "IsAllowNewTenantPurchase", "SortOrder"); - - b.ToTable("tenant_packages", null, t => - { - t.HasComment("平台提供的租户套餐定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantPayment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("支付金额。"); - - b.Property("BillingStatementId") - .HasColumnType("bigint") - .HasComment("关联的账单 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Method") - .HasColumnType("integer") - .HasComment("支付方式。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付时间。"); - - b.Property("ProofUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("支付凭证 URL。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TransactionNo") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("交易号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "BillingStatementId"); - - b.ToTable("tenant_payments", null, t => - { - t.HasComment("租户支付记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaPackagePurchase", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiredAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(可选)。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("购买价格。"); - - b.Property("PurchasedAt") - .HasColumnType("timestamp with time zone") - .HasComment("购买时间。"); - - b.Property("QuotaPackageId") - .HasColumnType("bigint") - .HasComment("配额包 ID。"); - - b.Property("QuotaValue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("购买时的配额值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "QuotaPackageId", "PurchasedAt"); - - b.ToTable("tenant_quota_package_purchases", null, t => - { - t.HasComment("租户配额包购买记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaUsage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LastResetAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次重置时间。"); - - b.Property("LimitValue") - .HasColumnType("numeric") - .HasComment("当前配额上限。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型,例如门店数、短信条数等。"); - - b.Property("ResetCycle") - .HasColumnType("text") - .HasComment("配额刷新周期描述(如月、年)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedValue") - .HasColumnType("numeric") - .HasComment("已消耗的数量。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "QuotaType") - .IsUnique(); - - b.ToTable("tenant_quota_usages", null, t => - { - t.HasComment("租户配额使用情况快照。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantReviewClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ClaimedAt") - .HasColumnType("timestamp with time zone") - .HasComment("领取时间(UTC)。"); - - b.Property("ClaimedBy") - .HasColumnType("bigint") - .HasComment("领取人用户 ID。"); - - b.Property("ClaimedByName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("领取人名称(展示用快照)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReleasedAt") - .HasColumnType("timestamp with time zone") - .HasComment("释放时间(UTC),未释放时为 null。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("被领取的租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("ClaimedBy"); - - b.HasIndex("TenantId") - .IsUnique() - .HasFilter("\"ReleasedAt\" IS NULL AND \"DeletedAt\" IS NULL"); - - b.ToTable("tenant_review_claims", null, t => - { - t.HasComment("租户入驻审核领取记录(防止多管理员并发审核)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscription", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AutoRenew") - .HasColumnType("boolean") - .HasComment("是否开启自动续费。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("订阅生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("订阅到期时间(UTC)。"); - - b.Property("NextBillingDate") - .HasColumnType("timestamp with time zone") - .HasComment("下一个计费时间,配合自动续费使用。"); - - b.Property("Notes") - .HasColumnType("text") - .HasComment("运营备注信息。"); - - b.Property("ScheduledPackageId") - .HasColumnType("bigint") - .HasComment("若已排期升降配,对应的新套餐 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("订阅当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TenantPackageId") - .HasColumnType("bigint") - .HasComment("当前订阅关联的套餐标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantPackageId"); - - b.ToTable("tenant_subscriptions", null, t => - { - t.HasComment("租户套餐订阅记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscriptionHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasColumnType("numeric") - .HasComment("相关费用。"); - - b.Property("ChangeType") - .HasColumnType("integer") - .HasComment("变更类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Currency") - .HasMaxLength(8) - .HasColumnType("character varying(8)") - .HasComment("币种。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("FromPackageId") - .HasColumnType("bigint") - .HasComment("原套餐 ID。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("租户标识。"); - - b.Property("TenantSubscriptionId") - .HasColumnType("bigint") - .HasComment("对应的订阅 ID。"); - - b.Property("ToPackageId") - .HasColumnType("bigint") - .HasComment("新套餐 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantSubscriptionId"); - - b.ToTable("tenant_subscription_histories", null, t => - { - t.HasComment("租户套餐订阅变更记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantVerificationProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdditionalDataJson") - .HasColumnType("text") - .HasComment("附加资料(JSON)。"); - - b.Property("BankAccountName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("开户名。"); - - b.Property("BankAccountNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("银行账号。"); - - b.Property("BankName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("银行名称。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照编号。"); - - b.Property("BusinessLicenseUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营业执照文件地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LegalPersonIdBackUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证反面。"); - - b.Property("LegalPersonIdFrontUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证正面。"); - - b.Property("LegalPersonIdNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("法人身份证号。"); - - b.Property("LegalPersonName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人姓名。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注。"); - - b.Property("ReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核时间。"); - - b.Property("ReviewedBy") - .HasColumnType("bigint") - .HasComment("审核人 ID。"); - - b.Property("ReviewedByName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("审核人姓名。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("实名状态。"); - - b.Property("SubmittedAt") - .HasColumnType("timestamp with time zone") - .HasComment("提交时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("对应的租户标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId") - .IsUnique(); - - b.ToTable("tenant_verification_profiles", null, t => - { - t.HasComment("租户实名认证资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.HasOne("TakeoutSaaS.Domain.Orders.Entities.Order", null) - .WithMany() - .HasForeignKey("OrderId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251217092209_AddQuotaPackagesAndPayments.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251217092209_AddQuotaPackagesAndPayments.cs deleted file mode 100644 index 79238e8..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251217092209_AddQuotaPackagesAndPayments.cs +++ /dev/null @@ -1,164 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - /// - public partial class AddQuotaPackagesAndPayments : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "operation_logs", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - OperationType = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "操作类型:BatchExtend, BatchRemind, StatusChange 等。"), - TargetType = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "目标类型:Subscription, Bill 等。"), - TargetIds = table.Column(type: "text", nullable: true, comment: "目标ID列表(JSON)。"), - OperatorId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "操作人ID。"), - OperatorName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true, comment: "操作人名称。"), - Parameters = table.Column(type: "text", nullable: true, comment: "操作参数(JSON)。"), - Result = table.Column(type: "text", nullable: true, comment: "操作结果(JSON)。"), - Success = table.Column(type: "boolean", nullable: false, comment: "是否成功。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。") - }, - constraints: table => - { - table.PrimaryKey("PK_operation_logs", x => x.Id); - }, - comment: "运营操作日志。"); - - migrationBuilder.CreateTable( - name: "quota_packages", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, comment: "配额包名称。"), - QuotaType = table.Column(type: "integer", nullable: false, comment: "配额类型。"), - QuotaValue = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false, comment: "配额数值。"), - Price = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false, comment: "价格。"), - IsActive = table.Column(type: "boolean", nullable: false, comment: "是否上架。"), - SortOrder = table.Column(type: "integer", nullable: false, defaultValue: 0, comment: "排序。"), - Description = table.Column(type: "character varying(512)", maxLength: 512, nullable: true, comment: "描述。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。") - }, - constraints: table => - { - table.PrimaryKey("PK_quota_packages", x => x.Id); - }, - comment: "配额包定义(平台提供的可购买配额包)。"); - - migrationBuilder.CreateTable( - name: "tenant_payments", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - BillingStatementId = table.Column(type: "bigint", nullable: false, comment: "关联的账单 ID。"), - Amount = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false, comment: "支付金额。"), - Method = table.Column(type: "integer", nullable: false, comment: "支付方式。"), - Status = table.Column(type: "integer", nullable: false, comment: "支付状态。"), - TransactionNo = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "交易号。"), - ProofUrl = table.Column(type: "character varying(512)", maxLength: 512, nullable: true, comment: "支付凭证 URL。"), - PaidAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "支付时间。"), - Notes = table.Column(type: "character varying(512)", maxLength: 512, nullable: true, comment: "备注信息。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_tenant_payments", x => x.Id); - }, - comment: "租户支付记录。"); - - migrationBuilder.CreateTable( - name: "tenant_quota_package_purchases", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - QuotaPackageId = table.Column(type: "bigint", nullable: false, comment: "配额包 ID。"), - QuotaValue = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false, comment: "购买时的配额值。"), - Price = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false, comment: "购买价格。"), - PurchasedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "购买时间。"), - ExpiredAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "过期时间(可选)。"), - Notes = table.Column(type: "character varying(512)", maxLength: 512, nullable: true, comment: "备注。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_tenant_quota_package_purchases", x => x.Id); - }, - comment: "租户配额包购买记录。"); - - migrationBuilder.CreateIndex( - name: "IX_operation_logs_CreatedAt", - table: "operation_logs", - column: "CreatedAt"); - - migrationBuilder.CreateIndex( - name: "IX_operation_logs_OperationType_CreatedAt", - table: "operation_logs", - columns: new[] { "OperationType", "CreatedAt" }); - - migrationBuilder.CreateIndex( - name: "IX_quota_packages_QuotaType_IsActive_SortOrder", - table: "quota_packages", - columns: new[] { "QuotaType", "IsActive", "SortOrder" }); - - migrationBuilder.CreateIndex( - name: "IX_tenant_payments_TenantId_BillingStatementId", - table: "tenant_payments", - columns: new[] { "TenantId", "BillingStatementId" }); - - migrationBuilder.CreateIndex( - name: "IX_tenant_quota_package_purchases_TenantId_QuotaPackageId_Purc~", - table: "tenant_quota_package_purchases", - columns: new[] { "TenantId", "QuotaPackageId", "PurchasedAt" }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "operation_logs"); - - migrationBuilder.DropTable( - name: "quota_packages"); - - migrationBuilder.DropTable( - name: "tenant_payments"); - - migrationBuilder.DropTable( - name: "tenant_quota_package_purchases"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251217160046_UpdateTenantBillingSchema.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251217160046_UpdateTenantBillingSchema.Designer.cs deleted file mode 100644 index 45e6d39..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251217160046_UpdateTenantBillingSchema.Designer.cs +++ /dev/null @@ -1,7174 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.App.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - [DbContext(typeof(TakeoutAppDbContext))] - [Migration("20251217160046_UpdateTenantBillingSchema")] - partial class UpdateTenantBillingSchema - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricAlertRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionJson") - .IsRequired() - .HasColumnType("text") - .HasComment("触发条件 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Enabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("关联指标。"); - - b.Property("NotificationChannels") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("通知渠道。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("告警级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "Severity"); - - b.ToTable("metric_alert_rules", null, t => - { - t.HasComment("指标告警规则。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricDefinition", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("指标编码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultAggregation") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("默认聚合方式。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("说明。"); - - b.Property("DimensionsJson") - .HasColumnType("text") - .HasComment("维度描述 JSON。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("指标名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("metric_definitions", null, t => - { - t.HasComment("指标定义,描述可观测的数据点。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricSnapshot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DimensionKey") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("维度键(JSON)。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("指标定义 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Value") - .HasPrecision(18, 4) - .HasColumnType("numeric(18,4)") - .HasComment("数值。"); - - b.Property("WindowEnd") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口结束。"); - - b.Property("WindowStart") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口开始。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "DimensionKey", "WindowStart", "WindowEnd") - .IsUnique(); - - b.ToTable("metric_snapshots", null, t => - { - t.HasComment("指标快照,用于大盘展示。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.Coupon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("券码或序列号。"); - - b.Property("CouponTemplateId") - .HasColumnType("bigint") - .HasComment("模板标识。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("发放时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID(已使用时记录)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedAt") - .HasColumnType("timestamp with time zone") - .HasComment("使用时间。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("归属用户。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("coupons", null, t => - { - t.HasComment("用户领取的券。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.CouponTemplate", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowStack") - .HasColumnType("boolean") - .HasComment("是否允许叠加其他优惠。"); - - b.Property("ChannelsJson") - .HasColumnType("text") - .HasComment("发放渠道(JSON)。"); - - b.Property("ClaimedQuantity") - .HasColumnType("integer") - .HasComment("已领取数量。"); - - b.Property("CouponType") - .HasColumnType("integer") - .HasComment("券类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("DiscountCap") - .HasColumnType("numeric") - .HasComment("折扣上限(针对折扣券)。"); - - b.Property("MinimumSpend") - .HasColumnType("numeric") - .HasComment("最低消费门槛。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("模板名称。"); - - b.Property("ProductScopeJson") - .HasColumnType("text") - .HasComment("适用品类或商品范围(JSON)。"); - - b.Property("RelativeValidDays") - .HasColumnType("integer") - .HasComment("有效天数(相对发放时间)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreScopeJson") - .HasColumnType("text") - .HasComment("适用门店 ID 集合(JSON)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TotalQuantity") - .HasColumnType("integer") - .HasComment("总发放数量上限。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ValidFrom") - .HasColumnType("timestamp with time zone") - .HasComment("可用开始时间。"); - - b.Property("ValidTo") - .HasColumnType("timestamp with time zone") - .HasComment("可用结束时间。"); - - b.Property("Value") - .HasColumnType("numeric") - .HasComment("面值或折扣额度。"); - - b.HasKey("Id"); - - b.ToTable("coupon_templates", null, t => - { - t.HasComment("优惠券模板。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.PromotionCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AudienceDescription") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("目标人群描述。"); - - b.Property("BannerUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营销素材(如 banner)。"); - - b.Property("Budget") - .HasColumnType("numeric") - .HasComment("预算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("PromotionType") - .HasColumnType("integer") - .HasComment("活动类型。"); - - b.Property("RulesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("活动规则 JSON。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("活动状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("promotion_campaigns", null, t => - { - t.HasComment("营销活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChatSessionId") - .HasColumnType("bigint") - .HasComment("会话标识。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("消息内容。"); - - b.Property("ContentType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("消息类型(文字/图片/语音等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRead") - .HasColumnType("boolean") - .HasComment("是否已读。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("读取时间。"); - - b.Property("SenderType") - .HasColumnType("integer") - .HasComment("发送方类型。"); - - b.Property("SenderUserId") - .HasColumnType("bigint") - .HasComment("发送方用户 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ChatSessionId", "CreatedAt"); - - b.ToTable("chat_messages", null, t => - { - t.HasComment("会话消息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AgentUserId") - .HasColumnType("bigint") - .HasComment("当前客服员工 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("顾客用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndedAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("IsBotActive") - .HasColumnType("boolean") - .HasComment("是否机器人接待中。"); - - b.Property("SessionCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话编号。"); - - b.Property("StartedAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店(可空为平台)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionCode") - .IsUnique(); - - b.ToTable("chat_sessions", null, t => - { - t.HasComment("客服会话。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.SupportTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AssignedAgentId") - .HasColumnType("bigint") - .HasComment("指派的客服。"); - - b.Property("ClosedAt") - .HasColumnType("timestamp with time zone") - .HasComment("关闭时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("客户用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .IsRequired() - .HasColumnType("text") - .HasComment("工单详情。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单(如有)。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("优先级。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("Subject") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("工单主题。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("工单编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TicketNo") - .IsUnique(); - - b.ToTable("support_tickets", null, t => - { - t.HasComment("客服工单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.TicketComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttachmentsJson") - .HasColumnType("text") - .HasComment("附件 JSON。"); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人 ID。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsInternal") - .HasColumnType("boolean") - .HasComment("是否内部备注。"); - - b.Property("SupportTicketId") - .HasColumnType("bigint") - .HasComment("工单标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SupportTicketId"); - - b.ToTable("ticket_comments", null, t => - { - t.HasComment("工单评论/流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryEvent", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryOrderId") - .HasColumnType("bigint") - .HasComment("配送单标识。"); - - b.Property("EventType") - .HasColumnType("integer") - .HasComment("事件类型。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("事件描述。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始数据 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DeliveryOrderId", "EventType"); - - b.ToTable("delivery_events", null, t => - { - t.HasComment("配送状态事件流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CourierName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("骑手姓名。"); - - b.Property("CourierPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("骑手电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveredAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("DispatchedAt") - .HasColumnType("timestamp with time zone") - .HasComment("下发时间。"); - - b.Property("FailureReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("异常原因。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("获取或设置关联订单 ID。"); - - b.Property("PickedUpAt") - .HasColumnType("timestamp with time zone") - .HasComment("取餐时间。"); - - b.Property("Provider") - .HasColumnType("integer") - .HasComment("配送服务商。"); - - b.Property("ProviderOrderId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方配送单号。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId") - .IsUnique(); - - b.ToTable("delivery_orders", null, t => - { - t.HasComment("配送单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliateOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("推广人标识。"); - - b.Property("BuyerUserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedCommission") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("预计佣金。"); - - b.Property("OrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("订单金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("SettledAt") - .HasColumnType("timestamp with time zone") - .HasComment("结算完成时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "OrderId") - .IsUnique(); - - b.ToTable("affiliate_orders", null, t => - { - t.HasComment("分销订单记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePartner", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChannelType") - .HasColumnType("integer") - .HasComment("渠道类型。"); - - b.Property("CommissionRate") - .HasColumnType("numeric") - .HasComment("分成比例(0-1)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称或渠道名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID(如绑定平台账号)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DisplayName"); - - b.ToTable("affiliate_partners", null, t => - { - t.HasComment("分销/推广合作伙伴。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePayout", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("合作伙伴标识。"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("结算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("打款时间。"); - - b.Property("Period") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("结算周期描述。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "Period") - .IsUnique(); - - b.ToTable("affiliate_payouts", null, t => - { - t.HasComment("佣金结算记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowMakeupCount") - .HasColumnType("integer") - .HasComment("支持补签次数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("活动描述。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("结束日期。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("RewardsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("连签奖励 JSON。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("开始日期。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name"); - - b.ToTable("checkin_campaigns", null, t => - { - t.HasComment("签到活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CheckInCampaignId") - .HasColumnType("bigint") - .HasComment("活动标识。"); - - b.Property("CheckInDate") - .HasColumnType("timestamp with time zone") - .HasComment("签到日期(本地)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsMakeup") - .HasColumnType("boolean") - .HasComment("是否补签。"); - - b.Property("RewardJson") - .IsRequired() - .HasColumnType("text") - .HasComment("获得奖励 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "CheckInCampaignId", "UserId", "CheckInDate") - .IsUnique(); - - b.ToTable("checkin_records", null, t => - { - t.HasComment("用户签到记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsDeleted") - .HasColumnType("boolean") - .HasComment("状态。"); - - b.Property("ParentId") - .HasColumnType("bigint") - .HasComment("父级评论 ID。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "CreatedAt"); - - b.ToTable("community_comments", null, t => - { - t.HasComment("社区评论。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityPost", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("作者用户 ID。"); - - b.Property("CommentCount") - .HasColumnType("integer") - .HasComment("评论数。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LikeCount") - .HasColumnType("integer") - .HasComment("点赞数。"); - - b.Property("MediaJson") - .HasColumnType("text") - .HasComment("媒体资源 JSON。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AuthorUserId", "CreatedAt"); - - b.ToTable("community_posts", null, t => - { - t.HasComment("社区动态。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityReaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态 ID。"); - - b.Property("ReactedAt") - .HasColumnType("timestamp with time zone") - .HasComment("时间戳。"); - - b.Property("ReactionType") - .HasColumnType("integer") - .HasComment("反应类型。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "UserId") - .IsUnique(); - - b.ToTable("community_reactions", null, t => - { - t.HasComment("社区互动反馈。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentCount") - .HasColumnType("integer") - .HasComment("当前已参与人数。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("GroupOrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("拼单编号。"); - - b.Property("GroupPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("拼团价格。"); - - b.Property("LeaderUserId") - .HasColumnType("bigint") - .HasComment("团长用户 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("关联商品或套餐。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("拼团状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("SucceededAt") - .HasColumnType("timestamp with time zone") - .HasComment("成团时间。"); - - b.Property("TargetCount") - .HasColumnType("integer") - .HasComment("成团需要的人数。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderNo") - .IsUnique(); - - b.ToTable("group_orders", null, t => - { - t.HasComment("拼单活动。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupParticipant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GroupOrderId") - .HasColumnType("bigint") - .HasComment("拼单活动标识。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("参与时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("对应订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("参与状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderId", "UserId") - .IsUnique(); - - b.ToTable("group_participants", null, t => - { - t.HasComment("拼单参与者。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryAdjustment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdjustmentType") - .HasColumnType("integer") - .HasComment("调整类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("InventoryItemId") - .HasColumnType("bigint") - .HasComment("对应的库存记录标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("调整数量,正数增加,负数减少。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("原因说明。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "InventoryItemId", "OccurredAt"); - - b.ToTable("inventory_adjustments", null, t => - { - t.HasComment("库存调整记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryBatch", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("ProductionDate") - .HasColumnType("timestamp with time zone") - .HasComment("生产日期。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("入库数量。"); - - b.Property("RemainingQuantity") - .HasColumnType("integer") - .HasComment("剩余数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber") - .IsUnique(); - - b.ToTable("inventory_batches", null, t => - { - t.HasComment("SKU 批次信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchConsumeStrategy") - .HasColumnType("integer") - .HasComment("批次扣减策略。"); - - b.Property("BatchNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号,可为空表示混批。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售商品。"); - - b.Property("IsSoldOut") - .HasColumnType("boolean") - .HasComment("是否标记售罄。"); - - b.Property("Location") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("储位或仓位信息。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单品限购(覆盖商品级 MaxQuantityPerOrder)。"); - - b.Property("PresaleCapacity") - .HasColumnType("integer") - .HasComment("预售名额(上限)。"); - - b.Property("PresaleEndTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售结束时间(UTC)。"); - - b.Property("PresaleLocked") - .HasColumnType("integer") - .HasComment("当前预售已锁定数量。"); - - b.Property("PresaleStartTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售开始时间(UTC)。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("QuantityOnHand") - .HasColumnType("integer") - .HasComment("可用库存。"); - - b.Property("QuantityReserved") - .HasColumnType("integer") - .HasComment("已锁定库存(订单占用)。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("SafetyStock") - .HasColumnType("integer") - .HasComment("安全库存阈值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber"); - - b.ToTable("inventory_items", null, t => - { - t.HasComment("SKU 在门店的库存信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryLockRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("IdempotencyKey") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("幂等键。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售锁定。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU ID。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("锁定数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("锁定状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "IdempotencyKey") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "Status"); - - b.ToTable("inventory_lock_records", null, t => - { - t.HasComment("库存锁定记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberGrowthLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChangeValue") - .HasColumnType("integer") - .HasComment("变动数量。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentValue") - .HasColumnType("integer") - .HasComment("当前成长值。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_growth_logs", null, t => - { - t.HasComment("成长值变动日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberPointLedger", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BalanceAfterChange") - .HasColumnType("integer") - .HasComment("变动后余额。"); - - b.Property("ChangeAmount") - .HasColumnType("integer") - .HasComment("变动数量,可为负值。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(如适用)。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Reason") - .HasColumnType("integer") - .HasComment("变动原因。"); - - b.Property("SourceId") - .HasColumnType("bigint") - .HasComment("来源 ID(订单、活动等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_point_ledgers", null, t => - { - t.HasComment("积分变动流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AvatarUrl") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像。"); - - b.Property("BirthDate") - .HasColumnType("timestamp with time zone") - .HasComment("生日。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GrowthValue") - .HasColumnType("integer") - .HasComment("成长值/经验值。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("注册时间。"); - - b.Property("MemberTierId") - .HasColumnType("bigint") - .HasComment("当前会员等级 ID。"); - - b.Property("Mobile") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("Nickname") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称。"); - - b.Property("PointsBalance") - .HasColumnType("integer") - .HasComment("会员积分余额。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会员状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Mobile") - .IsUnique(); - - b.ToTable("member_profiles", null, t => - { - t.HasComment("会员档案。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberTier", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BenefitsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("等级权益(JSON)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("等级名称。"); - - b.Property("RequiredGrowth") - .HasColumnType("integer") - .HasComment("所需成长值。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("member_tiers", null, t => - { - t.HasComment("会员等级定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.Merchant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("BrandAlias") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("品牌简称或别名。"); - - b.Property("BrandName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("品牌名称(对外展示)。"); - - b.Property("BusinessLicenseImageUrl") - .HasColumnType("text") - .HasComment("营业执照扫描件地址。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照号。"); - - b.Property("Category") - .HasColumnType("text") - .HasComment("品牌所属品类,如火锅、咖啡等。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("联系邮箱。"); - - b.Property("ContactPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在区县。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("入驻时间。"); - - b.Property("LastReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次审核时间。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度信息。"); - - b.Property("LegalPerson") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人或负责人姓名。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("品牌 Logo。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度信息。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注或驳回原因。"); - - b.Property("ServicePhone") - .HasColumnType("text") - .HasComment("客服电话。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("入驻状态。"); - - b.Property("SupportEmail") - .HasColumnType("text") - .HasComment("客服邮箱。"); - - b.Property("TaxNumber") - .HasColumnType("text") - .HasComment("税号/统一社会信用代码。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.ToTable("merchants", null, t => - { - t.HasComment("商户主体信息,承载入驻和资质审核结果。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantAuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("动作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("详情描述。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("商户标识。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId"); - - b.ToTable("merchant_audit_logs", null, t => - { - t.HasComment("商户入驻审核日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("显示顺序,越小越靠前。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否可用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("类目名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("merchant_categories", null, t => - { - t.HasComment("商户可选类目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantContract", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ContractNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("合同编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同结束时间。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("合同文件存储地址。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("SignedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签署时间。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("合同状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TerminatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("终止时间。"); - - b.Property("TerminationReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("终止原因。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "ContractNumber") - .IsUnique(); - - b.ToTable("merchant_contracts", null, t => - { - t.HasComment("商户合同记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantDocument", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DocumentNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("证照编号。"); - - b.Property("DocumentType") - .HasColumnType("integer") - .HasComment("证照类型。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期日期。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("证照文件链接。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签发日期。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Remarks") - .HasColumnType("text") - .HasComment("审核备注或驳回原因。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("审核状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "DocumentType"); - - b.ToTable("merchant_documents", null, t => - { - t.HasComment("商户提交的资质或证照材料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantStaff", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Email") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("邮箱地址。"); - - b.Property("IdentityUserId") - .HasColumnType("bigint") - .HasComment("登录账号 ID(指向统一身份体系)。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("员工姓名。"); - - b.Property("PermissionsJson") - .HasColumnType("text") - .HasComment("自定义权限(JSON)。"); - - b.Property("Phone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("员工角色类型。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("员工状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("可选的关联门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "Phone"); - - b.ToTable("merchant_staff", null, t => - { - t.HasComment("商户员工账号,支持门店维度分配。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.MapLocation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Landmark") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("打车/导航落点描述。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("名称。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店 ID,可空表示独立 POI。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("map_locations", null, t => - { - t.HasComment("地图 POI 信息,用于门店定位和推荐。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.NavigationRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("来源通道(小程序、H5 等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("请求时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TargetApp") - .HasColumnType("integer") - .HasComment("跳转的地图应用。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId", "RequestedAt"); - - b.ToTable("navigation_requests", null, t => - { - t.HasComment("用户发起的导航请求日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("扩展 JSON(规格、加料选项等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品或 SKU 标识。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称快照。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("自定义备注(口味要求)。"); - - b.Property("ShoppingCartId") - .HasColumnType("bigint") - .HasComment("所属购物车标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价快照。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ShoppingCartId"); - - b.ToTable("cart_items", null, t => - { - t.HasComment("购物车条目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItemAddon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CartItemId") - .HasColumnType("bigint") - .HasComment("所属购物车条目。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("OptionId") - .HasColumnType("bigint") - .HasComment("选项 ID(可对应 ProductAddonOption)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("cart_item_addons", null, t => - { - t.HasComment("购物车条目的加料/附加项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CheckoutSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("SessionToken") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话 Token。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.Property("ValidationResultJson") - .IsRequired() - .HasColumnType("text") - .HasComment("校验结果明细 JSON。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionToken") - .IsUnique(); - - b.ToTable("checkout_sessions", null, t => - { - t.HasComment("结账会话,记录校验上下文。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.ShoppingCart", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryPreference") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("履约方式(堂食/自提/配送)缓存。"); - - b.Property("LastModifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次修改时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("购物车状态,包含正常/锁定。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableContext") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌码或场景标识(扫码点餐)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId") - .IsUnique(); - - b.ToTable("shopping_carts", null, t => - { - t.HasComment("用户购物车,按租户/门店隔离。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.Order", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("取消原因。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("下单渠道。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("顾客姓名。"); - - b.Property("CustomerPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("顾客手机号。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryType") - .HasColumnType("integer") - .HasComment("履约类型。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("优惠金额。"); - - b.Property("FinishedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("ItemsAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("商品总额。"); - - b.Property("OrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("订单号。"); - - b.Property("PaidAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付时间。"); - - b.Property("PayableAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额。"); - - b.Property("PaymentStatus") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("QueueNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队号(如有)。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationId") - .HasColumnType("bigint") - .HasComment("预约 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TableNo") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("就餐桌号。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "Status"); - - b.ToTable("orders", null, t => - { - t.HasComment("交易订单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("自定义属性 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("折扣金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品 ID。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("SkuName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("SKU/规格描述。"); - - b.Property("SubTotal") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("小计。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("单位。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("OrderId"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("order_items", null, t => - { - t.HasComment("订单明细。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderStatusHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注信息。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识(可为空表示系统)。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("变更后的状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId", "OccurredAt"); - - b.ToTable("order_status_histories", null, t => - { - t.HasComment("订单状态流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.RefundRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("申请金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("ProcessedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核完成时间。"); - - b.Property("Reason") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("申请原因。"); - - b.Property("RefundNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("退款单号。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("用户提交时间。"); - - b.Property("ReviewNotes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "RefundNo") - .IsUnique(); - - b.ToTable("refund_requests", null, t => - { - t.HasComment("售后/退款申请。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("支付金额。"); - - b.Property("ChannelTransactionId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方渠道单号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Method") - .HasColumnType("integer") - .HasComment("支付方式。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付完成时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始回调内容。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("错误/备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TradeNo") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("平台交易号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("payment_records", null, t => - { - t.HasComment("支付流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRefundRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("退款金额。"); - - b.Property("ChannelRefundId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("渠道退款流水号。"); - - b.Property("CompletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("渠道返回的原始数据 JSON。"); - - b.Property("PaymentRecordId") - .HasColumnType("bigint") - .HasComment("原支付记录标识。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("退款请求时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PaymentRecordId"); - - b.ToTable("payment_refund_records", null, t => - { - t.HasComment("支付渠道退款流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.Product", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CategoryId") - .HasColumnType("bigint") - .HasComment("所属分类。"); - - b.Property("CoverImage") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("主图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("商品描述。"); - - b.Property("EnableDelivery") - .HasColumnType("boolean") - .HasComment("支持配送。"); - - b.Property("EnableDineIn") - .HasColumnType("boolean") - .HasComment("支持堂食。"); - - b.Property("EnablePickup") - .HasColumnType("boolean") - .HasComment("支持自提。"); - - b.Property("GalleryImages") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Gallery 图片逗号分隔。"); - - b.Property("IsFeatured") - .HasColumnType("boolean") - .HasComment("是否热门推荐。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("最大每单限购。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("现价。"); - - b.Property("SpuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("商品编码。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("商品状态。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("库存数量(可选)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("Subtitle") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("副标题/卖点。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("售卖单位(份/杯等)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SpuCode") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("products", null, t => - { - t.HasComment("商品(SPU)信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("MaxSelect") - .HasColumnType("integer") - .HasComment("最大选择数量。"); - - b.Property("MinSelect") - .HasColumnType("integer") - .HasComment("最小选择数量。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "Name"); - - b.ToTable("product_addon_groups", null, t => - { - t.HasComment("加料/做法分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AddonGroupId") - .HasColumnType("bigint") - .HasComment("所属加料分组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选项。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("product_addon_options", null, t => - { - t.HasComment("加料选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称,例如“辣度”“份量”。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型(单选/多选)。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("显示排序。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店,可为空表示所有门店共享。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("product_attribute_groups", null, t => - { - t.HasComment("商品规格/属性分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributeGroupId") - .HasColumnType("bigint") - .HasComment("所属规格组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选中。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AttributeGroupId", "Name") - .IsUnique(); - - b.ToTable("product_attribute_options", null, t => - { - t.HasComment("商品规格选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("分类描述。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分类名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("product_categories", null, t => - { - t.HasComment("商品分类。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductMediaAsset", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Caption") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述或标题。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MediaType") - .HasColumnType("integer") - .HasComment("媒体类型。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品标识。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Url") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("媒资链接。"); - - b.HasKey("Id"); - - b.ToTable("product_media_assets", null, t => - { - t.HasComment("商品媒资素材。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductPricingRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("条件描述(JSON),如会员等级、渠道等。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效结束时间。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("特殊价格。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("RuleType") - .HasColumnType("integer") - .HasComment("策略类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StartTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效开始时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("WeekdaysJson") - .HasColumnType("text") - .HasComment("生效星期(JSON 数组)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "RuleType"); - - b.ToTable("product_pricing_rules", null, t => - { - t.HasComment("商品价格策略,支持会员价/时段价等。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductSku", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("规格属性 JSON(记录选项 ID)。"); - - b.Property("Barcode") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("条形码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("售价。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SkuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("SKU 编码。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("可售库存。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weight") - .HasPrecision(10, 3) - .HasColumnType("numeric(10,3)") - .HasComment("重量(千克)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SkuCode") - .IsUnique(); - - b.ToTable("product_skus", null, t => - { - t.HasComment("商品 SKU,记录具体规格组合价格。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Queues.Entities.QueueTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CalledAt") - .HasColumnType("timestamp with time zone") - .HasComment("叫号时间。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedWaitMinutes") - .HasColumnType("integer") - .HasComment("预计等待分钟。"); - - b.Property("ExpiredAt") - .HasColumnType("timestamp with time zone") - .HasComment("过号时间。"); - - b.Property("PartySize") - .HasColumnType("integer") - .HasComment("就餐人数。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("获取或设置所属门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNumber") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.HasIndex("TenantId", "StoreId", "TicketNumber") - .IsUnique(); - - b.ToTable("queue_tickets", null, t => - { - t.HasComment("排队叫号。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Reservations.Entities.Reservation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CheckInCode") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("核销码/到店码。"); - - b.Property("CheckedInAt") - .HasColumnType("timestamp with time zone") - .HasComment("实际签到时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("客户姓名。"); - - b.Property("CustomerPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PeopleCount") - .HasColumnType("integer") - .HasComment("用餐人数。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("预约号。"); - - b.Property("ReservationTime") - .HasColumnType("timestamp with time zone") - .HasComment("预约时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TablePreference") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌型/标签。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ReservationNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("reservations", null, t => - { - t.HasComment("预约/预订记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.Store", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("Announcement") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("门店公告。"); - - b.Property("BusinessHours") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("门店营业时段描述(备用字符串)。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("门店编码,便于扫码及外部对接。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家或地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("门店海报。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryRadiusKm") - .HasPrecision(6, 2) - .HasColumnType("numeric(6,2)") - .HasComment("默认配送半径(公里)。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("门店描述或公告。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区县信息。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("高德/腾讯地图经度。"); - - b.Property("ManagerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("门店负责人姓名。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("门店名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("门店当前运营状态。"); - - b.Property("SupportsDelivery") - .HasColumnType("boolean") - .HasComment("是否支持配送。"); - - b.Property("SupportsDineIn") - .HasColumnType("boolean") - .HasComment("是否支持堂食。"); - - b.Property("SupportsPickup") - .HasColumnType("boolean") - .HasComment("是否支持自提。"); - - b.Property("SupportsQueueing") - .HasColumnType("boolean") - .HasComment("支持排队叫号。"); - - b.Property("SupportsReservation") - .HasColumnType("boolean") - .HasComment("支持预约。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("门店标签(逗号分隔)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.HasIndex("TenantId", "MerchantId"); - - b.ToTable("stores", null, t => - { - t.HasComment("门店信息,承载营业配置与能力。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreBusinessHour", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CapacityLimit") - .HasColumnType("integer") - .HasComment("最大接待容量或单量限制。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DayOfWeek") - .HasColumnType("integer") - .HasComment("星期几,0 表示周日。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间(本地时间)。"); - - b.Property("HourType") - .HasColumnType("integer") - .HasComment("时段类型(正常营业、休息、预约等)。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间(本地时间)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "DayOfWeek"); - - b.ToTable("store_business_hours", null, t => - { - t.HasComment("门店营业时段配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreDeliveryZone", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("EstimatedMinutes") - .HasColumnType("integer") - .HasComment("预计送达分钟。"); - - b.Property("MinimumOrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("起送价。"); - - b.Property("PolygonGeoJson") - .IsRequired() - .HasColumnType("text") - .HasComment("GeoJSON 表示的多边形范围。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ZoneName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ZoneName"); - - b.ToTable("store_delivery_zones", null, t => - { - t.HasComment("门店配送范围配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreEmployeeShift", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("排班角色。"); - - b.Property("ShiftDate") - .HasColumnType("timestamp with time zone") - .HasComment("班次日期。"); - - b.Property("StaffId") - .HasColumnType("bigint") - .HasComment("员工标识。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ShiftDate", "StaffId") - .IsUnique(); - - b.ToTable("store_employee_shifts", null, t => - { - t.HasComment("门店员工排班记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreHoliday", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Date") - .HasColumnType("timestamp with time zone") - .HasComment("日期。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsClosed") - .HasColumnType("boolean") - .HasComment("是否全天闭店。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("说明内容。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Date") - .IsUnique(); - - b.ToTable("store_holidays", null, t => - { - t.HasComment("门店休息日或特殊营业日。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSetting", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowDaysAhead") - .HasColumnType("integer") - .HasComment("可预约天数(含当天)。"); - - b.Property("AllowToday") - .HasColumnType("boolean") - .HasComment("是否允许当天自提。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultCutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("默认截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单笔自提最大份数。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId") - .IsUnique(); - - b.ToTable("store_pickup_settings", null, t => - { - t.HasComment("门店自提配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSlot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("容量(份数)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("当天结束时间(UTC)。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("档期名称。"); - - b.Property("ReservedCount") - .HasColumnType("integer") - .HasComment("已占用数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("当天开始时间(UTC)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weekdays") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("适用星期(逗号分隔 1-7)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("store_pickup_slots", null, t => - { - t.HasComment("门店自提档期。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTable", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AreaId") - .HasColumnType("bigint") - .HasComment("所在区域 ID。"); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("可容纳人数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("QrCodeUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("桌码二维码地址。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前桌台状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("桌码。"); - - b.Property("Tags") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("桌台标签(堂食、快餐等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "TableCode") - .IsUnique(); - - b.ToTable("store_tables", null, t => - { - t.HasComment("桌台信息与二维码绑定。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTableArea", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("区域描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name") - .IsUnique(); - - b.ToTable("store_table_areas", null, t => - { - t.HasComment("门店桌台区域配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.OperationLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OperationType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作类型:BatchExtend, BatchRemind, StatusChange 等。"); - - b.Property("OperatorId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人ID。"); - - b.Property("OperatorName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("操作人名称。"); - - b.Property("Parameters") - .HasColumnType("text") - .HasComment("操作参数(JSON)。"); - - b.Property("Result") - .HasColumnType("text") - .HasComment("操作结果(JSON)。"); - - b.Property("Success") - .HasColumnType("boolean") - .HasComment("是否成功。"); - - b.Property("TargetIds") - .HasColumnType("text") - .HasComment("目标ID列表(JSON)。"); - - b.Property("TargetType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("目标类型:Subscription, Bill 等。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("CreatedAt"); - - b.HasIndex("OperationType", "CreatedAt"); - - b.ToTable("operation_logs", null, t => - { - t.HasComment("运营操作日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.QuotaPackage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("描述。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否上架。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("配额包名称。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("价格。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型。"); - - b.Property("QuotaValue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配额数值。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("排序。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("QuotaType", "IsActive", "SortOrder"); - - b.ToTable("quota_packages", null, t => - { - t.HasComment("配额包定义(平台提供的可购买配额包)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.Tenant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("text") - .HasComment("详细地址信息。"); - - b.Property("City") - .HasColumnType("text") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("租户短编码,作为跨系统引用的唯一标识。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("主联系人邮箱。"); - - b.Property("ContactName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("主联系人姓名。"); - - b.Property("ContactPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("主联系人电话。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家/地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("品牌海报或封面图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("服务生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("服务到期时间(UTC)。"); - - b.Property("Industry") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所属行业,如餐饮、零售等。"); - - b.Property("LegalEntityName") - .HasColumnType("text") - .HasComment("法人或公司主体名称。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("LOGO 图片地址。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("租户全称或品牌名称。"); - - b.Property("PrimaryOwnerUserId") - .HasColumnType("bigint") - .HasComment("系统内对应的租户所有者账号 ID。"); - - b.Property("Province") - .HasColumnType("text") - .HasComment("所在省份或州。"); - - b.Property("Remarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息,用于运营记录特殊说明。"); - - b.Property("ShortName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("对外展示的简称。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("租户当前状态,涵盖审核、启用、停用等场景。"); - - b.Property("SuspendedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次暂停服务时间。"); - - b.Property("SuspensionReason") - .HasColumnType("text") - .HasComment("暂停或终止的原因说明。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("业务标签集合(逗号分隔)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Website") - .HasColumnType("text") - .HasComment("官网或主要宣传链接。"); - - b.HasKey("Id"); - - b.HasIndex("Code") - .IsUnique(); - - b.HasIndex("ContactPhone") - .IsUnique(); - - b.ToTable("tenants", null, t => - { - t.HasComment("平台租户信息,描述租户的生命周期与基础资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementType") - .HasColumnType("integer") - .HasComment("公告类型。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("公告正文(可为 Markdown/HTML,前端自行渲染)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("失效时间(UTC),为空表示长期有效。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("展示优先级,数值越大越靠前。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("公告标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AnnouncementType", "IsActive"); - - b.HasIndex("TenantId", "EffectiveFrom", "EffectiveTo"); - - b.ToTable("tenant_announcements", null, t => - { - t.HasComment("租户公告。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncementRead", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementId") - .HasColumnType("bigint") - .HasComment("公告 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("已读时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("已读用户 ID(后台账号),为空表示租户级已读。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AnnouncementId", "UserId") - .IsUnique(); - - b.ToTable("tenant_announcement_reads", null, t => - { - t.HasComment("租户公告已读记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("操作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentStatus") - .HasColumnType("integer") - .HasComment("新状态。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("详细描述。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人名称。"); - - b.Property("PreviousStatus") - .HasColumnType("integer") - .HasComment("原状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("关联的租户标识。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("日志标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.ToTable("tenant_audit_logs", null, t => - { - t.HasComment("租户运营审核日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantBillingStatement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AmountDue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额(原始金额)。"); - - b.Property("AmountPaid") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("BillingType") - .HasColumnType("integer") - .HasComment("账单类型(订阅账单/配额包账单/手动账单/续费账单)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Currency") - .IsRequired() - .ValueGeneratedOnAdd() - .HasMaxLength(8) - .HasColumnType("character varying(8)") - .HasDefaultValue("CNY") - .HasComment("货币类型(默认 CNY)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("折扣金额。"); - - b.Property("DueDate") - .HasColumnType("timestamp with time zone") - .HasComment("到期日。"); - - b.Property("LineItemsJson") - .HasColumnType("text") - .HasComment("账单明细 JSON,记录各项费用。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息(如:人工备注、取消原因等)。"); - - b.Property("OverdueNotifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("逾期通知时间。"); - - b.Property("PeriodEnd") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期结束时间。"); - - b.Property("PeriodStart") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期开始时间。"); - - b.Property("ReminderSentAt") - .HasColumnType("timestamp with time zone") - .HasComment("提醒发送时间(续费提醒、逾期提醒等)。"); - - b.Property("StatementNo") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("账单编号,供对账查询。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前付款状态。"); - - b.Property("SubscriptionId") - .HasColumnType("bigint") - .HasComment("关联的订阅 ID(仅当 BillingType 为 Subscription 或 Renewal 时有值)。"); - - b.Property("TaxAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("税费金额。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("CreatedAt") - .HasDatabaseName("idx_billing_created_at"); - - b.HasIndex("Status", "DueDate") - .HasDatabaseName("idx_billing_status_duedate") - .HasFilter("\"Status\" IN (0, 2)"); - - b.HasIndex("TenantId", "StatementNo") - .IsUnique(); - - b.HasIndex("TenantId", "Status", "DueDate") - .HasDatabaseName("idx_billing_tenant_status_duedate"); - - b.ToTable("tenant_billing_statements", null, t => - { - t.HasComment("租户账单,用于呈现周期性收费。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantNotification", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("发布通道(站内、邮件、短信等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("通知正文。"); - - b.Property("MetadataJson") - .HasColumnType("text") - .HasComment("附加元数据 JSON。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("租户是否已阅读。"); - - b.Property("SentAt") - .HasColumnType("timestamp with time zone") - .HasComment("推送时间。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("通知重要级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("通知标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Channel", "SentAt"); - - b.ToTable("tenant_notifications", null, t => - { - t.HasComment("面向租户的站内通知或消息推送。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantPackage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("套餐描述,包含适用场景、权益等。"); - - b.Property("FeaturePoliciesJson") - .HasColumnType("text") - .HasComment("权益明细 JSON,记录自定义特性开关。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否仍启用(平台控制)。"); - - b.Property("IsAllowNewTenantPurchase") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否允许新租户购买/选择(仅影响新购)。"); - - b.Property("IsPublicVisible") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否对外可见(展示页/套餐列表可见性)。"); - - b.Property("IsRecommended") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false) - .HasComment("是否推荐展示(运营推荐标识)。"); - - b.Property("MaxAccountCount") - .HasColumnType("integer") - .HasComment("允许创建的最大账号数。"); - - b.Property("MaxDeliveryOrders") - .HasColumnType("integer") - .HasComment("每月可调用的配送单数量上限。"); - - b.Property("MaxSmsCredits") - .HasColumnType("integer") - .HasComment("每月短信额度上限。"); - - b.Property("MaxStorageGb") - .HasColumnType("integer") - .HasComment("存储容量上限(GB)。"); - - b.Property("MaxStoreCount") - .HasColumnType("integer") - .HasComment("允许的最大门店数。"); - - b.Property("MonthlyPrice") - .HasColumnType("numeric") - .HasComment("月付价格,单位:人民币元。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("套餐名称,展示给租户的简称。"); - - b.Property("PackageType") - .HasColumnType("integer") - .HasComment("套餐分类(试用、标准、旗舰等)。"); - - b.Property("PublishStatus") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("发布状态:0=草稿,1=已发布。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("展示排序,数值越小越靠前。"); - - b.PrimitiveCollection("Tags") - .IsRequired() - .HasColumnType("text[]") - .HasComment("套餐标签(用于展示与对比页)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("YearlyPrice") - .HasColumnType("numeric") - .HasComment("年付价格,单位:人民币元。"); - - b.HasKey("Id"); - - b.HasIndex("IsActive", "SortOrder"); - - b.HasIndex("PublishStatus", "IsActive", "IsPublicVisible", "IsAllowNewTenantPurchase", "SortOrder"); - - b.ToTable("tenant_packages", null, t => - { - t.HasComment("平台提供的租户套餐定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantPayment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("支付金额。"); - - b.Property("BillingStatementId") - .HasColumnType("bigint") - .HasComment("关联的账单 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Method") - .HasColumnType("integer") - .HasComment("支付方式。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付时间。"); - - b.Property("ProofUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("支付凭证 URL。"); - - b.Property("RefundReason") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("退款原因。"); - - b.Property("RefundedAt") - .HasColumnType("timestamp with time zone") - .HasComment("退款时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TransactionNo") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("交易号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("VerifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核时间。"); - - b.Property("VerifiedBy") - .HasColumnType("bigint") - .HasComment("审核人 ID(管理员)。"); - - b.HasKey("Id"); - - b.HasIndex("TransactionNo") - .HasDatabaseName("idx_payment_transaction_no") - .HasFilter("\"TransactionNo\" IS NOT NULL"); - - b.HasIndex("BillingStatementId", "PaidAt") - .HasDatabaseName("idx_payment_billing_paidat"); - - b.HasIndex("TenantId", "BillingStatementId"); - - b.ToTable("tenant_payments", null, t => - { - t.HasComment("租户支付记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaPackagePurchase", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiredAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(可选)。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("购买价格。"); - - b.Property("PurchasedAt") - .HasColumnType("timestamp with time zone") - .HasComment("购买时间。"); - - b.Property("QuotaPackageId") - .HasColumnType("bigint") - .HasComment("配额包 ID。"); - - b.Property("QuotaValue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("购买时的配额值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "QuotaPackageId", "PurchasedAt"); - - b.ToTable("tenant_quota_package_purchases", null, t => - { - t.HasComment("租户配额包购买记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaUsage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LastResetAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次重置时间。"); - - b.Property("LimitValue") - .HasColumnType("numeric") - .HasComment("当前配额上限。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型,例如门店数、短信条数等。"); - - b.Property("ResetCycle") - .HasColumnType("text") - .HasComment("配额刷新周期描述(如月、年)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedValue") - .HasColumnType("numeric") - .HasComment("已消耗的数量。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "QuotaType") - .IsUnique(); - - b.ToTable("tenant_quota_usages", null, t => - { - t.HasComment("租户配额使用情况快照。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantReviewClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ClaimedAt") - .HasColumnType("timestamp with time zone") - .HasComment("领取时间(UTC)。"); - - b.Property("ClaimedBy") - .HasColumnType("bigint") - .HasComment("领取人用户 ID。"); - - b.Property("ClaimedByName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("领取人名称(展示用快照)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReleasedAt") - .HasColumnType("timestamp with time zone") - .HasComment("释放时间(UTC),未释放时为 null。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("被领取的租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("ClaimedBy"); - - b.HasIndex("TenantId") - .IsUnique() - .HasFilter("\"ReleasedAt\" IS NULL AND \"DeletedAt\" IS NULL"); - - b.ToTable("tenant_review_claims", null, t => - { - t.HasComment("租户入驻审核领取记录(防止多管理员并发审核)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscription", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AutoRenew") - .HasColumnType("boolean") - .HasComment("是否开启自动续费。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("订阅生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("订阅到期时间(UTC)。"); - - b.Property("NextBillingDate") - .HasColumnType("timestamp with time zone") - .HasComment("下一个计费时间,配合自动续费使用。"); - - b.Property("Notes") - .HasColumnType("text") - .HasComment("运营备注信息。"); - - b.Property("ScheduledPackageId") - .HasColumnType("bigint") - .HasComment("若已排期升降配,对应的新套餐 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("订阅当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TenantPackageId") - .HasColumnType("bigint") - .HasComment("当前订阅关联的套餐标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantPackageId"); - - b.ToTable("tenant_subscriptions", null, t => - { - t.HasComment("租户套餐订阅记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscriptionHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasColumnType("numeric") - .HasComment("相关费用。"); - - b.Property("ChangeType") - .HasColumnType("integer") - .HasComment("变更类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Currency") - .HasMaxLength(8) - .HasColumnType("character varying(8)") - .HasComment("币种。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("FromPackageId") - .HasColumnType("bigint") - .HasComment("原套餐 ID。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("租户标识。"); - - b.Property("TenantSubscriptionId") - .HasColumnType("bigint") - .HasComment("对应的订阅 ID。"); - - b.Property("ToPackageId") - .HasColumnType("bigint") - .HasComment("新套餐 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantSubscriptionId"); - - b.ToTable("tenant_subscription_histories", null, t => - { - t.HasComment("租户套餐订阅变更记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantVerificationProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdditionalDataJson") - .HasColumnType("text") - .HasComment("附加资料(JSON)。"); - - b.Property("BankAccountName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("开户名。"); - - b.Property("BankAccountNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("银行账号。"); - - b.Property("BankName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("银行名称。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照编号。"); - - b.Property("BusinessLicenseUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营业执照文件地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LegalPersonIdBackUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证反面。"); - - b.Property("LegalPersonIdFrontUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证正面。"); - - b.Property("LegalPersonIdNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("法人身份证号。"); - - b.Property("LegalPersonName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人姓名。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注。"); - - b.Property("ReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核时间。"); - - b.Property("ReviewedBy") - .HasColumnType("bigint") - .HasComment("审核人 ID。"); - - b.Property("ReviewedByName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("审核人姓名。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("实名状态。"); - - b.Property("SubmittedAt") - .HasColumnType("timestamp with time zone") - .HasComment("提交时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("对应的租户标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId") - .IsUnique(); - - b.ToTable("tenant_verification_profiles", null, t => - { - t.HasComment("租户实名认证资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.HasOne("TakeoutSaaS.Domain.Orders.Entities.Order", null) - .WithMany() - .HasForeignKey("OrderId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251217160046_UpdateTenantBillingSchema.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251217160046_UpdateTenantBillingSchema.cs deleted file mode 100644 index 6a882f2..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251217160046_UpdateTenantBillingSchema.cs +++ /dev/null @@ -1,237 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - /// - public partial class UpdateTenantBillingSchema : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "RefundReason", - table: "tenant_payments", - type: "character varying(512)", - maxLength: 512, - nullable: true, - comment: "退款原因。"); - - migrationBuilder.AddColumn( - name: "RefundedAt", - table: "tenant_payments", - type: "timestamp with time zone", - nullable: true, - comment: "退款时间。"); - - migrationBuilder.AddColumn( - name: "VerifiedAt", - table: "tenant_payments", - type: "timestamp with time zone", - nullable: true, - comment: "审核时间。"); - - migrationBuilder.AddColumn( - name: "VerifiedBy", - table: "tenant_payments", - type: "bigint", - nullable: true, - comment: "审核人 ID(管理员)。"); - - migrationBuilder.AlterColumn( - name: "AmountDue", - table: "tenant_billing_statements", - type: "numeric(18,2)", - precision: 18, - scale: 2, - nullable: false, - comment: "应付金额(原始金额)。", - oldClrType: typeof(decimal), - oldType: "numeric(18,2)", - oldPrecision: 18, - oldScale: 2, - oldComment: "应付金额。"); - - migrationBuilder.AddColumn( - name: "BillingType", - table: "tenant_billing_statements", - type: "integer", - nullable: false, - defaultValue: 0, - comment: "账单类型(订阅账单/配额包账单/手动账单/续费账单)。"); - - migrationBuilder.AddColumn( - name: "Currency", - table: "tenant_billing_statements", - type: "character varying(8)", - maxLength: 8, - nullable: false, - defaultValue: "CNY", - comment: "货币类型(默认 CNY)。"); - - migrationBuilder.AddColumn( - name: "DiscountAmount", - table: "tenant_billing_statements", - type: "numeric(18,2)", - precision: 18, - scale: 2, - nullable: false, - defaultValue: 0m, - comment: "折扣金额。"); - - migrationBuilder.AddColumn( - name: "Notes", - table: "tenant_billing_statements", - type: "character varying(512)", - maxLength: 512, - nullable: true, - comment: "备注信息(如:人工备注、取消原因等)。"); - - migrationBuilder.AddColumn( - name: "OverdueNotifiedAt", - table: "tenant_billing_statements", - type: "timestamp with time zone", - nullable: true, - comment: "逾期通知时间。"); - - migrationBuilder.AddColumn( - name: "ReminderSentAt", - table: "tenant_billing_statements", - type: "timestamp with time zone", - nullable: true, - comment: "提醒发送时间(续费提醒、逾期提醒等)。"); - - migrationBuilder.AddColumn( - name: "SubscriptionId", - table: "tenant_billing_statements", - type: "bigint", - nullable: true, - comment: "关联的订阅 ID(仅当 BillingType 为 Subscription 或 Renewal 时有值)。"); - - migrationBuilder.AddColumn( - name: "TaxAmount", - table: "tenant_billing_statements", - type: "numeric(18,2)", - precision: 18, - scale: 2, - nullable: false, - defaultValue: 0m, - comment: "税费金额。"); - - migrationBuilder.CreateIndex( - name: "idx_payment_billing_paidat", - table: "tenant_payments", - columns: new[] { "BillingStatementId", "PaidAt" }); - - migrationBuilder.CreateIndex( - name: "idx_payment_transaction_no", - table: "tenant_payments", - column: "TransactionNo", - filter: "\"TransactionNo\" IS NOT NULL"); - - migrationBuilder.CreateIndex( - name: "idx_billing_created_at", - table: "tenant_billing_statements", - column: "CreatedAt"); - - migrationBuilder.CreateIndex( - name: "idx_billing_status_duedate", - table: "tenant_billing_statements", - columns: new[] { "Status", "DueDate" }, - filter: "\"Status\" IN (0, 2)"); - - migrationBuilder.CreateIndex( - name: "idx_billing_tenant_status_duedate", - table: "tenant_billing_statements", - columns: new[] { "TenantId", "Status", "DueDate" }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "idx_payment_billing_paidat", - table: "tenant_payments"); - - migrationBuilder.DropIndex( - name: "idx_payment_transaction_no", - table: "tenant_payments"); - - migrationBuilder.DropIndex( - name: "idx_billing_created_at", - table: "tenant_billing_statements"); - - migrationBuilder.DropIndex( - name: "idx_billing_status_duedate", - table: "tenant_billing_statements"); - - migrationBuilder.DropIndex( - name: "idx_billing_tenant_status_duedate", - table: "tenant_billing_statements"); - - migrationBuilder.DropColumn( - name: "RefundReason", - table: "tenant_payments"); - - migrationBuilder.DropColumn( - name: "RefundedAt", - table: "tenant_payments"); - - migrationBuilder.DropColumn( - name: "VerifiedAt", - table: "tenant_payments"); - - migrationBuilder.DropColumn( - name: "VerifiedBy", - table: "tenant_payments"); - - migrationBuilder.DropColumn( - name: "BillingType", - table: "tenant_billing_statements"); - - migrationBuilder.DropColumn( - name: "Currency", - table: "tenant_billing_statements"); - - migrationBuilder.DropColumn( - name: "DiscountAmount", - table: "tenant_billing_statements"); - - migrationBuilder.DropColumn( - name: "Notes", - table: "tenant_billing_statements"); - - migrationBuilder.DropColumn( - name: "OverdueNotifiedAt", - table: "tenant_billing_statements"); - - migrationBuilder.DropColumn( - name: "ReminderSentAt", - table: "tenant_billing_statements"); - - migrationBuilder.DropColumn( - name: "SubscriptionId", - table: "tenant_billing_statements"); - - migrationBuilder.DropColumn( - name: "TaxAmount", - table: "tenant_billing_statements"); - - migrationBuilder.AlterColumn( - name: "AmountDue", - table: "tenant_billing_statements", - type: "numeric(18,2)", - precision: 18, - scale: 2, - nullable: false, - comment: "应付金额。", - oldClrType: typeof(decimal), - oldType: "numeric(18,2)", - oldPrecision: 18, - oldScale: 2, - oldComment: "应付金额(原始金额)。"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251218121053_AddTenantQuotaUsageHistories.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251218121053_AddTenantQuotaUsageHistories.Designer.cs deleted file mode 100644 index 8d634ae..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251218121053_AddTenantQuotaUsageHistories.Designer.cs +++ /dev/null @@ -1,7252 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.App.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - [DbContext(typeof(TakeoutAppDbContext))] - [Migration("20251218121053_AddTenantQuotaUsageHistories")] - partial class AddTenantQuotaUsageHistories - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricAlertRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionJson") - .IsRequired() - .HasColumnType("text") - .HasComment("触发条件 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Enabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("关联指标。"); - - b.Property("NotificationChannels") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("通知渠道。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("告警级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "Severity"); - - b.ToTable("metric_alert_rules", null, t => - { - t.HasComment("指标告警规则。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricDefinition", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("指标编码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultAggregation") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("默认聚合方式。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("说明。"); - - b.Property("DimensionsJson") - .HasColumnType("text") - .HasComment("维度描述 JSON。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("指标名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("metric_definitions", null, t => - { - t.HasComment("指标定义,描述可观测的数据点。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricSnapshot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DimensionKey") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("维度键(JSON)。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("指标定义 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Value") - .HasPrecision(18, 4) - .HasColumnType("numeric(18,4)") - .HasComment("数值。"); - - b.Property("WindowEnd") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口结束。"); - - b.Property("WindowStart") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口开始。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "DimensionKey", "WindowStart", "WindowEnd") - .IsUnique(); - - b.ToTable("metric_snapshots", null, t => - { - t.HasComment("指标快照,用于大盘展示。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.Coupon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("券码或序列号。"); - - b.Property("CouponTemplateId") - .HasColumnType("bigint") - .HasComment("模板标识。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("发放时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID(已使用时记录)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedAt") - .HasColumnType("timestamp with time zone") - .HasComment("使用时间。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("归属用户。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("coupons", null, t => - { - t.HasComment("用户领取的券。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.CouponTemplate", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowStack") - .HasColumnType("boolean") - .HasComment("是否允许叠加其他优惠。"); - - b.Property("ChannelsJson") - .HasColumnType("text") - .HasComment("发放渠道(JSON)。"); - - b.Property("ClaimedQuantity") - .HasColumnType("integer") - .HasComment("已领取数量。"); - - b.Property("CouponType") - .HasColumnType("integer") - .HasComment("券类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("DiscountCap") - .HasColumnType("numeric") - .HasComment("折扣上限(针对折扣券)。"); - - b.Property("MinimumSpend") - .HasColumnType("numeric") - .HasComment("最低消费门槛。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("模板名称。"); - - b.Property("ProductScopeJson") - .HasColumnType("text") - .HasComment("适用品类或商品范围(JSON)。"); - - b.Property("RelativeValidDays") - .HasColumnType("integer") - .HasComment("有效天数(相对发放时间)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreScopeJson") - .HasColumnType("text") - .HasComment("适用门店 ID 集合(JSON)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TotalQuantity") - .HasColumnType("integer") - .HasComment("总发放数量上限。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ValidFrom") - .HasColumnType("timestamp with time zone") - .HasComment("可用开始时间。"); - - b.Property("ValidTo") - .HasColumnType("timestamp with time zone") - .HasComment("可用结束时间。"); - - b.Property("Value") - .HasColumnType("numeric") - .HasComment("面值或折扣额度。"); - - b.HasKey("Id"); - - b.ToTable("coupon_templates", null, t => - { - t.HasComment("优惠券模板。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.PromotionCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AudienceDescription") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("目标人群描述。"); - - b.Property("BannerUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营销素材(如 banner)。"); - - b.Property("Budget") - .HasColumnType("numeric") - .HasComment("预算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("PromotionType") - .HasColumnType("integer") - .HasComment("活动类型。"); - - b.Property("RulesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("活动规则 JSON。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("活动状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("promotion_campaigns", null, t => - { - t.HasComment("营销活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChatSessionId") - .HasColumnType("bigint") - .HasComment("会话标识。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("消息内容。"); - - b.Property("ContentType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("消息类型(文字/图片/语音等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRead") - .HasColumnType("boolean") - .HasComment("是否已读。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("读取时间。"); - - b.Property("SenderType") - .HasColumnType("integer") - .HasComment("发送方类型。"); - - b.Property("SenderUserId") - .HasColumnType("bigint") - .HasComment("发送方用户 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ChatSessionId", "CreatedAt"); - - b.ToTable("chat_messages", null, t => - { - t.HasComment("会话消息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AgentUserId") - .HasColumnType("bigint") - .HasComment("当前客服员工 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("顾客用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndedAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("IsBotActive") - .HasColumnType("boolean") - .HasComment("是否机器人接待中。"); - - b.Property("SessionCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话编号。"); - - b.Property("StartedAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店(可空为平台)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionCode") - .IsUnique(); - - b.ToTable("chat_sessions", null, t => - { - t.HasComment("客服会话。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.SupportTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AssignedAgentId") - .HasColumnType("bigint") - .HasComment("指派的客服。"); - - b.Property("ClosedAt") - .HasColumnType("timestamp with time zone") - .HasComment("关闭时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("客户用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .IsRequired() - .HasColumnType("text") - .HasComment("工单详情。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单(如有)。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("优先级。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("Subject") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("工单主题。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("工单编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TicketNo") - .IsUnique(); - - b.ToTable("support_tickets", null, t => - { - t.HasComment("客服工单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.TicketComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttachmentsJson") - .HasColumnType("text") - .HasComment("附件 JSON。"); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人 ID。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsInternal") - .HasColumnType("boolean") - .HasComment("是否内部备注。"); - - b.Property("SupportTicketId") - .HasColumnType("bigint") - .HasComment("工单标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SupportTicketId"); - - b.ToTable("ticket_comments", null, t => - { - t.HasComment("工单评论/流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryEvent", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryOrderId") - .HasColumnType("bigint") - .HasComment("配送单标识。"); - - b.Property("EventType") - .HasColumnType("integer") - .HasComment("事件类型。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("事件描述。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始数据 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DeliveryOrderId", "EventType"); - - b.ToTable("delivery_events", null, t => - { - t.HasComment("配送状态事件流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CourierName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("骑手姓名。"); - - b.Property("CourierPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("骑手电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveredAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("DispatchedAt") - .HasColumnType("timestamp with time zone") - .HasComment("下发时间。"); - - b.Property("FailureReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("异常原因。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("获取或设置关联订单 ID。"); - - b.Property("PickedUpAt") - .HasColumnType("timestamp with time zone") - .HasComment("取餐时间。"); - - b.Property("Provider") - .HasColumnType("integer") - .HasComment("配送服务商。"); - - b.Property("ProviderOrderId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方配送单号。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId") - .IsUnique(); - - b.ToTable("delivery_orders", null, t => - { - t.HasComment("配送单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliateOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("推广人标识。"); - - b.Property("BuyerUserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedCommission") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("预计佣金。"); - - b.Property("OrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("订单金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("SettledAt") - .HasColumnType("timestamp with time zone") - .HasComment("结算完成时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "OrderId") - .IsUnique(); - - b.ToTable("affiliate_orders", null, t => - { - t.HasComment("分销订单记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePartner", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChannelType") - .HasColumnType("integer") - .HasComment("渠道类型。"); - - b.Property("CommissionRate") - .HasColumnType("numeric") - .HasComment("分成比例(0-1)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称或渠道名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID(如绑定平台账号)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DisplayName"); - - b.ToTable("affiliate_partners", null, t => - { - t.HasComment("分销/推广合作伙伴。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePayout", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("合作伙伴标识。"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("结算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("打款时间。"); - - b.Property("Period") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("结算周期描述。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "Period") - .IsUnique(); - - b.ToTable("affiliate_payouts", null, t => - { - t.HasComment("佣金结算记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowMakeupCount") - .HasColumnType("integer") - .HasComment("支持补签次数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("活动描述。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("结束日期。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("RewardsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("连签奖励 JSON。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("开始日期。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name"); - - b.ToTable("checkin_campaigns", null, t => - { - t.HasComment("签到活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CheckInCampaignId") - .HasColumnType("bigint") - .HasComment("活动标识。"); - - b.Property("CheckInDate") - .HasColumnType("timestamp with time zone") - .HasComment("签到日期(本地)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsMakeup") - .HasColumnType("boolean") - .HasComment("是否补签。"); - - b.Property("RewardJson") - .IsRequired() - .HasColumnType("text") - .HasComment("获得奖励 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "CheckInCampaignId", "UserId", "CheckInDate") - .IsUnique(); - - b.ToTable("checkin_records", null, t => - { - t.HasComment("用户签到记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsDeleted") - .HasColumnType("boolean") - .HasComment("状态。"); - - b.Property("ParentId") - .HasColumnType("bigint") - .HasComment("父级评论 ID。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "CreatedAt"); - - b.ToTable("community_comments", null, t => - { - t.HasComment("社区评论。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityPost", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("作者用户 ID。"); - - b.Property("CommentCount") - .HasColumnType("integer") - .HasComment("评论数。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LikeCount") - .HasColumnType("integer") - .HasComment("点赞数。"); - - b.Property("MediaJson") - .HasColumnType("text") - .HasComment("媒体资源 JSON。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AuthorUserId", "CreatedAt"); - - b.ToTable("community_posts", null, t => - { - t.HasComment("社区动态。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityReaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态 ID。"); - - b.Property("ReactedAt") - .HasColumnType("timestamp with time zone") - .HasComment("时间戳。"); - - b.Property("ReactionType") - .HasColumnType("integer") - .HasComment("反应类型。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "UserId") - .IsUnique(); - - b.ToTable("community_reactions", null, t => - { - t.HasComment("社区互动反馈。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentCount") - .HasColumnType("integer") - .HasComment("当前已参与人数。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("GroupOrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("拼单编号。"); - - b.Property("GroupPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("拼团价格。"); - - b.Property("LeaderUserId") - .HasColumnType("bigint") - .HasComment("团长用户 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("关联商品或套餐。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("拼团状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("SucceededAt") - .HasColumnType("timestamp with time zone") - .HasComment("成团时间。"); - - b.Property("TargetCount") - .HasColumnType("integer") - .HasComment("成团需要的人数。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderNo") - .IsUnique(); - - b.ToTable("group_orders", null, t => - { - t.HasComment("拼单活动。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupParticipant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GroupOrderId") - .HasColumnType("bigint") - .HasComment("拼单活动标识。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("参与时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("对应订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("参与状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderId", "UserId") - .IsUnique(); - - b.ToTable("group_participants", null, t => - { - t.HasComment("拼单参与者。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryAdjustment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdjustmentType") - .HasColumnType("integer") - .HasComment("调整类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("InventoryItemId") - .HasColumnType("bigint") - .HasComment("对应的库存记录标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("调整数量,正数增加,负数减少。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("原因说明。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "InventoryItemId", "OccurredAt"); - - b.ToTable("inventory_adjustments", null, t => - { - t.HasComment("库存调整记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryBatch", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("ProductionDate") - .HasColumnType("timestamp with time zone") - .HasComment("生产日期。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("入库数量。"); - - b.Property("RemainingQuantity") - .HasColumnType("integer") - .HasComment("剩余数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber") - .IsUnique(); - - b.ToTable("inventory_batches", null, t => - { - t.HasComment("SKU 批次信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchConsumeStrategy") - .HasColumnType("integer") - .HasComment("批次扣减策略。"); - - b.Property("BatchNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号,可为空表示混批。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售商品。"); - - b.Property("IsSoldOut") - .HasColumnType("boolean") - .HasComment("是否标记售罄。"); - - b.Property("Location") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("储位或仓位信息。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单品限购(覆盖商品级 MaxQuantityPerOrder)。"); - - b.Property("PresaleCapacity") - .HasColumnType("integer") - .HasComment("预售名额(上限)。"); - - b.Property("PresaleEndTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售结束时间(UTC)。"); - - b.Property("PresaleLocked") - .HasColumnType("integer") - .HasComment("当前预售已锁定数量。"); - - b.Property("PresaleStartTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售开始时间(UTC)。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("QuantityOnHand") - .HasColumnType("integer") - .HasComment("可用库存。"); - - b.Property("QuantityReserved") - .HasColumnType("integer") - .HasComment("已锁定库存(订单占用)。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("SafetyStock") - .HasColumnType("integer") - .HasComment("安全库存阈值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber"); - - b.ToTable("inventory_items", null, t => - { - t.HasComment("SKU 在门店的库存信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryLockRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("IdempotencyKey") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("幂等键。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售锁定。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU ID。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("锁定数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("锁定状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "IdempotencyKey") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "Status"); - - b.ToTable("inventory_lock_records", null, t => - { - t.HasComment("库存锁定记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberGrowthLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChangeValue") - .HasColumnType("integer") - .HasComment("变动数量。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentValue") - .HasColumnType("integer") - .HasComment("当前成长值。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_growth_logs", null, t => - { - t.HasComment("成长值变动日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberPointLedger", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BalanceAfterChange") - .HasColumnType("integer") - .HasComment("变动后余额。"); - - b.Property("ChangeAmount") - .HasColumnType("integer") - .HasComment("变动数量,可为负值。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(如适用)。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Reason") - .HasColumnType("integer") - .HasComment("变动原因。"); - - b.Property("SourceId") - .HasColumnType("bigint") - .HasComment("来源 ID(订单、活动等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_point_ledgers", null, t => - { - t.HasComment("积分变动流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AvatarUrl") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像。"); - - b.Property("BirthDate") - .HasColumnType("timestamp with time zone") - .HasComment("生日。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GrowthValue") - .HasColumnType("integer") - .HasComment("成长值/经验值。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("注册时间。"); - - b.Property("MemberTierId") - .HasColumnType("bigint") - .HasComment("当前会员等级 ID。"); - - b.Property("Mobile") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("Nickname") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称。"); - - b.Property("PointsBalance") - .HasColumnType("integer") - .HasComment("会员积分余额。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会员状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Mobile") - .IsUnique(); - - b.ToTable("member_profiles", null, t => - { - t.HasComment("会员档案。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberTier", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BenefitsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("等级权益(JSON)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("等级名称。"); - - b.Property("RequiredGrowth") - .HasColumnType("integer") - .HasComment("所需成长值。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("member_tiers", null, t => - { - t.HasComment("会员等级定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.Merchant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("BrandAlias") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("品牌简称或别名。"); - - b.Property("BrandName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("品牌名称(对外展示)。"); - - b.Property("BusinessLicenseImageUrl") - .HasColumnType("text") - .HasComment("营业执照扫描件地址。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照号。"); - - b.Property("Category") - .HasColumnType("text") - .HasComment("品牌所属品类,如火锅、咖啡等。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("联系邮箱。"); - - b.Property("ContactPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在区县。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("入驻时间。"); - - b.Property("LastReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次审核时间。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度信息。"); - - b.Property("LegalPerson") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人或负责人姓名。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("品牌 Logo。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度信息。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注或驳回原因。"); - - b.Property("ServicePhone") - .HasColumnType("text") - .HasComment("客服电话。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("入驻状态。"); - - b.Property("SupportEmail") - .HasColumnType("text") - .HasComment("客服邮箱。"); - - b.Property("TaxNumber") - .HasColumnType("text") - .HasComment("税号/统一社会信用代码。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.ToTable("merchants", null, t => - { - t.HasComment("商户主体信息,承载入驻和资质审核结果。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantAuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("动作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("详情描述。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("商户标识。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId"); - - b.ToTable("merchant_audit_logs", null, t => - { - t.HasComment("商户入驻审核日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("显示顺序,越小越靠前。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否可用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("类目名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("merchant_categories", null, t => - { - t.HasComment("商户可选类目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantContract", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ContractNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("合同编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同结束时间。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("合同文件存储地址。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("SignedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签署时间。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("合同状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TerminatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("终止时间。"); - - b.Property("TerminationReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("终止原因。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "ContractNumber") - .IsUnique(); - - b.ToTable("merchant_contracts", null, t => - { - t.HasComment("商户合同记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantDocument", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DocumentNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("证照编号。"); - - b.Property("DocumentType") - .HasColumnType("integer") - .HasComment("证照类型。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期日期。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("证照文件链接。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签发日期。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Remarks") - .HasColumnType("text") - .HasComment("审核备注或驳回原因。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("审核状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "DocumentType"); - - b.ToTable("merchant_documents", null, t => - { - t.HasComment("商户提交的资质或证照材料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantStaff", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Email") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("邮箱地址。"); - - b.Property("IdentityUserId") - .HasColumnType("bigint") - .HasComment("登录账号 ID(指向统一身份体系)。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("员工姓名。"); - - b.Property("PermissionsJson") - .HasColumnType("text") - .HasComment("自定义权限(JSON)。"); - - b.Property("Phone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("员工角色类型。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("员工状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("可选的关联门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "Phone"); - - b.ToTable("merchant_staff", null, t => - { - t.HasComment("商户员工账号,支持门店维度分配。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.MapLocation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Landmark") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("打车/导航落点描述。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("名称。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店 ID,可空表示独立 POI。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("map_locations", null, t => - { - t.HasComment("地图 POI 信息,用于门店定位和推荐。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.NavigationRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("来源通道(小程序、H5 等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("请求时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TargetApp") - .HasColumnType("integer") - .HasComment("跳转的地图应用。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId", "RequestedAt"); - - b.ToTable("navigation_requests", null, t => - { - t.HasComment("用户发起的导航请求日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("扩展 JSON(规格、加料选项等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品或 SKU 标识。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称快照。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("自定义备注(口味要求)。"); - - b.Property("ShoppingCartId") - .HasColumnType("bigint") - .HasComment("所属购物车标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价快照。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ShoppingCartId"); - - b.ToTable("cart_items", null, t => - { - t.HasComment("购物车条目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItemAddon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CartItemId") - .HasColumnType("bigint") - .HasComment("所属购物车条目。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("OptionId") - .HasColumnType("bigint") - .HasComment("选项 ID(可对应 ProductAddonOption)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("cart_item_addons", null, t => - { - t.HasComment("购物车条目的加料/附加项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CheckoutSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("SessionToken") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话 Token。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.Property("ValidationResultJson") - .IsRequired() - .HasColumnType("text") - .HasComment("校验结果明细 JSON。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionToken") - .IsUnique(); - - b.ToTable("checkout_sessions", null, t => - { - t.HasComment("结账会话,记录校验上下文。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.ShoppingCart", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryPreference") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("履约方式(堂食/自提/配送)缓存。"); - - b.Property("LastModifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次修改时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("购物车状态,包含正常/锁定。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableContext") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌码或场景标识(扫码点餐)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId") - .IsUnique(); - - b.ToTable("shopping_carts", null, t => - { - t.HasComment("用户购物车,按租户/门店隔离。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.Order", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("取消原因。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("下单渠道。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("顾客姓名。"); - - b.Property("CustomerPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("顾客手机号。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryType") - .HasColumnType("integer") - .HasComment("履约类型。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("优惠金额。"); - - b.Property("FinishedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("ItemsAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("商品总额。"); - - b.Property("OrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("订单号。"); - - b.Property("PaidAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付时间。"); - - b.Property("PayableAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额。"); - - b.Property("PaymentStatus") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("QueueNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队号(如有)。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationId") - .HasColumnType("bigint") - .HasComment("预约 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TableNo") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("就餐桌号。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "Status"); - - b.ToTable("orders", null, t => - { - t.HasComment("交易订单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("自定义属性 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("折扣金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品 ID。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("SkuName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("SKU/规格描述。"); - - b.Property("SubTotal") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("小计。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("单位。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("OrderId"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("order_items", null, t => - { - t.HasComment("订单明细。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderStatusHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注信息。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识(可为空表示系统)。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("变更后的状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId", "OccurredAt"); - - b.ToTable("order_status_histories", null, t => - { - t.HasComment("订单状态流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.RefundRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("申请金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("ProcessedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核完成时间。"); - - b.Property("Reason") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("申请原因。"); - - b.Property("RefundNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("退款单号。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("用户提交时间。"); - - b.Property("ReviewNotes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "RefundNo") - .IsUnique(); - - b.ToTable("refund_requests", null, t => - { - t.HasComment("售后/退款申请。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("支付金额。"); - - b.Property("ChannelTransactionId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方渠道单号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Method") - .HasColumnType("integer") - .HasComment("支付方式。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付完成时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始回调内容。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("错误/备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TradeNo") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("平台交易号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("payment_records", null, t => - { - t.HasComment("支付流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRefundRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("退款金额。"); - - b.Property("ChannelRefundId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("渠道退款流水号。"); - - b.Property("CompletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("渠道返回的原始数据 JSON。"); - - b.Property("PaymentRecordId") - .HasColumnType("bigint") - .HasComment("原支付记录标识。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("退款请求时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PaymentRecordId"); - - b.ToTable("payment_refund_records", null, t => - { - t.HasComment("支付渠道退款流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.Product", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CategoryId") - .HasColumnType("bigint") - .HasComment("所属分类。"); - - b.Property("CoverImage") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("主图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("商品描述。"); - - b.Property("EnableDelivery") - .HasColumnType("boolean") - .HasComment("支持配送。"); - - b.Property("EnableDineIn") - .HasColumnType("boolean") - .HasComment("支持堂食。"); - - b.Property("EnablePickup") - .HasColumnType("boolean") - .HasComment("支持自提。"); - - b.Property("GalleryImages") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Gallery 图片逗号分隔。"); - - b.Property("IsFeatured") - .HasColumnType("boolean") - .HasComment("是否热门推荐。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("最大每单限购。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("现价。"); - - b.Property("SpuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("商品编码。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("商品状态。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("库存数量(可选)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("Subtitle") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("副标题/卖点。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("售卖单位(份/杯等)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SpuCode") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("products", null, t => - { - t.HasComment("商品(SPU)信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("MaxSelect") - .HasColumnType("integer") - .HasComment("最大选择数量。"); - - b.Property("MinSelect") - .HasColumnType("integer") - .HasComment("最小选择数量。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "Name"); - - b.ToTable("product_addon_groups", null, t => - { - t.HasComment("加料/做法分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AddonGroupId") - .HasColumnType("bigint") - .HasComment("所属加料分组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选项。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("product_addon_options", null, t => - { - t.HasComment("加料选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称,例如“辣度”“份量”。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型(单选/多选)。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("显示排序。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店,可为空表示所有门店共享。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("product_attribute_groups", null, t => - { - t.HasComment("商品规格/属性分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributeGroupId") - .HasColumnType("bigint") - .HasComment("所属规格组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选中。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AttributeGroupId", "Name") - .IsUnique(); - - b.ToTable("product_attribute_options", null, t => - { - t.HasComment("商品规格选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("分类描述。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分类名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("product_categories", null, t => - { - t.HasComment("商品分类。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductMediaAsset", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Caption") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述或标题。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MediaType") - .HasColumnType("integer") - .HasComment("媒体类型。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品标识。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Url") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("媒资链接。"); - - b.HasKey("Id"); - - b.ToTable("product_media_assets", null, t => - { - t.HasComment("商品媒资素材。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductPricingRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("条件描述(JSON),如会员等级、渠道等。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效结束时间。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("特殊价格。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("RuleType") - .HasColumnType("integer") - .HasComment("策略类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StartTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效开始时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("WeekdaysJson") - .HasColumnType("text") - .HasComment("生效星期(JSON 数组)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "RuleType"); - - b.ToTable("product_pricing_rules", null, t => - { - t.HasComment("商品价格策略,支持会员价/时段价等。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductSku", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("规格属性 JSON(记录选项 ID)。"); - - b.Property("Barcode") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("条形码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("售价。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SkuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("SKU 编码。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("可售库存。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weight") - .HasPrecision(10, 3) - .HasColumnType("numeric(10,3)") - .HasComment("重量(千克)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SkuCode") - .IsUnique(); - - b.ToTable("product_skus", null, t => - { - t.HasComment("商品 SKU,记录具体规格组合价格。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Queues.Entities.QueueTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CalledAt") - .HasColumnType("timestamp with time zone") - .HasComment("叫号时间。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedWaitMinutes") - .HasColumnType("integer") - .HasComment("预计等待分钟。"); - - b.Property("ExpiredAt") - .HasColumnType("timestamp with time zone") - .HasComment("过号时间。"); - - b.Property("PartySize") - .HasColumnType("integer") - .HasComment("就餐人数。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("获取或设置所属门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNumber") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.HasIndex("TenantId", "StoreId", "TicketNumber") - .IsUnique(); - - b.ToTable("queue_tickets", null, t => - { - t.HasComment("排队叫号。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Reservations.Entities.Reservation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CheckInCode") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("核销码/到店码。"); - - b.Property("CheckedInAt") - .HasColumnType("timestamp with time zone") - .HasComment("实际签到时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("客户姓名。"); - - b.Property("CustomerPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PeopleCount") - .HasColumnType("integer") - .HasComment("用餐人数。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("预约号。"); - - b.Property("ReservationTime") - .HasColumnType("timestamp with time zone") - .HasComment("预约时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TablePreference") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌型/标签。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ReservationNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("reservations", null, t => - { - t.HasComment("预约/预订记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.Store", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("Announcement") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("门店公告。"); - - b.Property("BusinessHours") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("门店营业时段描述(备用字符串)。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("门店编码,便于扫码及外部对接。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家或地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("门店海报。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryRadiusKm") - .HasPrecision(6, 2) - .HasColumnType("numeric(6,2)") - .HasComment("默认配送半径(公里)。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("门店描述或公告。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区县信息。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("高德/腾讯地图经度。"); - - b.Property("ManagerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("门店负责人姓名。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("门店名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("门店当前运营状态。"); - - b.Property("SupportsDelivery") - .HasColumnType("boolean") - .HasComment("是否支持配送。"); - - b.Property("SupportsDineIn") - .HasColumnType("boolean") - .HasComment("是否支持堂食。"); - - b.Property("SupportsPickup") - .HasColumnType("boolean") - .HasComment("是否支持自提。"); - - b.Property("SupportsQueueing") - .HasColumnType("boolean") - .HasComment("支持排队叫号。"); - - b.Property("SupportsReservation") - .HasColumnType("boolean") - .HasComment("支持预约。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("门店标签(逗号分隔)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.HasIndex("TenantId", "MerchantId"); - - b.ToTable("stores", null, t => - { - t.HasComment("门店信息,承载营业配置与能力。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreBusinessHour", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CapacityLimit") - .HasColumnType("integer") - .HasComment("最大接待容量或单量限制。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DayOfWeek") - .HasColumnType("integer") - .HasComment("星期几,0 表示周日。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间(本地时间)。"); - - b.Property("HourType") - .HasColumnType("integer") - .HasComment("时段类型(正常营业、休息、预约等)。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间(本地时间)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "DayOfWeek"); - - b.ToTable("store_business_hours", null, t => - { - t.HasComment("门店营业时段配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreDeliveryZone", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("EstimatedMinutes") - .HasColumnType("integer") - .HasComment("预计送达分钟。"); - - b.Property("MinimumOrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("起送价。"); - - b.Property("PolygonGeoJson") - .IsRequired() - .HasColumnType("text") - .HasComment("GeoJSON 表示的多边形范围。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ZoneName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ZoneName"); - - b.ToTable("store_delivery_zones", null, t => - { - t.HasComment("门店配送范围配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreEmployeeShift", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("排班角色。"); - - b.Property("ShiftDate") - .HasColumnType("timestamp with time zone") - .HasComment("班次日期。"); - - b.Property("StaffId") - .HasColumnType("bigint") - .HasComment("员工标识。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ShiftDate", "StaffId") - .IsUnique(); - - b.ToTable("store_employee_shifts", null, t => - { - t.HasComment("门店员工排班记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreHoliday", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Date") - .HasColumnType("timestamp with time zone") - .HasComment("日期。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsClosed") - .HasColumnType("boolean") - .HasComment("是否全天闭店。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("说明内容。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Date") - .IsUnique(); - - b.ToTable("store_holidays", null, t => - { - t.HasComment("门店休息日或特殊营业日。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSetting", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowDaysAhead") - .HasColumnType("integer") - .HasComment("可预约天数(含当天)。"); - - b.Property("AllowToday") - .HasColumnType("boolean") - .HasComment("是否允许当天自提。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultCutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("默认截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单笔自提最大份数。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId") - .IsUnique(); - - b.ToTable("store_pickup_settings", null, t => - { - t.HasComment("门店自提配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSlot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("容量(份数)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("当天结束时间(UTC)。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("档期名称。"); - - b.Property("ReservedCount") - .HasColumnType("integer") - .HasComment("已占用数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("当天开始时间(UTC)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weekdays") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("适用星期(逗号分隔 1-7)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("store_pickup_slots", null, t => - { - t.HasComment("门店自提档期。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTable", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AreaId") - .HasColumnType("bigint") - .HasComment("所在区域 ID。"); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("可容纳人数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("QrCodeUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("桌码二维码地址。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前桌台状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("桌码。"); - - b.Property("Tags") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("桌台标签(堂食、快餐等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "TableCode") - .IsUnique(); - - b.ToTable("store_tables", null, t => - { - t.HasComment("桌台信息与二维码绑定。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTableArea", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("区域描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name") - .IsUnique(); - - b.ToTable("store_table_areas", null, t => - { - t.HasComment("门店桌台区域配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.OperationLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OperationType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作类型:BatchExtend, BatchRemind, StatusChange 等。"); - - b.Property("OperatorId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人ID。"); - - b.Property("OperatorName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("操作人名称。"); - - b.Property("Parameters") - .HasColumnType("text") - .HasComment("操作参数(JSON)。"); - - b.Property("Result") - .HasColumnType("text") - .HasComment("操作结果(JSON)。"); - - b.Property("Success") - .HasColumnType("boolean") - .HasComment("是否成功。"); - - b.Property("TargetIds") - .HasColumnType("text") - .HasComment("目标ID列表(JSON)。"); - - b.Property("TargetType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("目标类型:Subscription, Bill 等。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("CreatedAt"); - - b.HasIndex("OperationType", "CreatedAt"); - - b.ToTable("operation_logs", null, t => - { - t.HasComment("运营操作日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.QuotaPackage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("描述。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否上架。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("配额包名称。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("价格。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型。"); - - b.Property("QuotaValue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配额数值。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("排序。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("QuotaType", "IsActive", "SortOrder"); - - b.ToTable("quota_packages", null, t => - { - t.HasComment("配额包定义(平台提供的可购买配额包)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.Tenant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("text") - .HasComment("详细地址信息。"); - - b.Property("City") - .HasColumnType("text") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("租户短编码,作为跨系统引用的唯一标识。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("主联系人邮箱。"); - - b.Property("ContactName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("主联系人姓名。"); - - b.Property("ContactPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("主联系人电话。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家/地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("品牌海报或封面图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("服务生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("服务到期时间(UTC)。"); - - b.Property("Industry") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所属行业,如餐饮、零售等。"); - - b.Property("LegalEntityName") - .HasColumnType("text") - .HasComment("法人或公司主体名称。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("LOGO 图片地址。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("租户全称或品牌名称。"); - - b.Property("PrimaryOwnerUserId") - .HasColumnType("bigint") - .HasComment("系统内对应的租户所有者账号 ID。"); - - b.Property("Province") - .HasColumnType("text") - .HasComment("所在省份或州。"); - - b.Property("Remarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息,用于运营记录特殊说明。"); - - b.Property("ShortName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("对外展示的简称。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("租户当前状态,涵盖审核、启用、停用等场景。"); - - b.Property("SuspendedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次暂停服务时间。"); - - b.Property("SuspensionReason") - .HasColumnType("text") - .HasComment("暂停或终止的原因说明。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("业务标签集合(逗号分隔)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Website") - .HasColumnType("text") - .HasComment("官网或主要宣传链接。"); - - b.HasKey("Id"); - - b.HasIndex("Code") - .IsUnique(); - - b.HasIndex("ContactPhone") - .IsUnique(); - - b.ToTable("tenants", null, t => - { - t.HasComment("平台租户信息,描述租户的生命周期与基础资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementType") - .HasColumnType("integer") - .HasComment("公告类型。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("公告正文(可为 Markdown/HTML,前端自行渲染)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("失效时间(UTC),为空表示长期有效。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("展示优先级,数值越大越靠前。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("公告标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AnnouncementType", "IsActive"); - - b.HasIndex("TenantId", "EffectiveFrom", "EffectiveTo"); - - b.ToTable("tenant_announcements", null, t => - { - t.HasComment("租户公告。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncementRead", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementId") - .HasColumnType("bigint") - .HasComment("公告 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("已读时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("已读用户 ID(后台账号),为空表示租户级已读。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AnnouncementId", "UserId") - .IsUnique(); - - b.ToTable("tenant_announcement_reads", null, t => - { - t.HasComment("租户公告已读记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("操作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentStatus") - .HasColumnType("integer") - .HasComment("新状态。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("详细描述。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人名称。"); - - b.Property("PreviousStatus") - .HasColumnType("integer") - .HasComment("原状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("关联的租户标识。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("日志标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.ToTable("tenant_audit_logs", null, t => - { - t.HasComment("租户运营审核日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantBillingStatement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AmountDue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额(原始金额)。"); - - b.Property("AmountPaid") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("BillingType") - .HasColumnType("integer") - .HasComment("账单类型(订阅账单/配额包账单/手动账单/续费账单)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Currency") - .IsRequired() - .ValueGeneratedOnAdd() - .HasMaxLength(8) - .HasColumnType("character varying(8)") - .HasDefaultValue("CNY") - .HasComment("货币类型(默认 CNY)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("折扣金额。"); - - b.Property("DueDate") - .HasColumnType("timestamp with time zone") - .HasComment("到期日。"); - - b.Property("LineItemsJson") - .HasColumnType("text") - .HasComment("账单明细 JSON,记录各项费用。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息(如:人工备注、取消原因等)。"); - - b.Property("OverdueNotifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("逾期通知时间。"); - - b.Property("PeriodEnd") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期结束时间。"); - - b.Property("PeriodStart") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期开始时间。"); - - b.Property("ReminderSentAt") - .HasColumnType("timestamp with time zone") - .HasComment("提醒发送时间(续费提醒、逾期提醒等)。"); - - b.Property("StatementNo") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("账单编号,供对账查询。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前付款状态。"); - - b.Property("SubscriptionId") - .HasColumnType("bigint") - .HasComment("关联的订阅 ID(仅当 BillingType 为 Subscription 或 Renewal 时有值)。"); - - b.Property("TaxAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("税费金额。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("CreatedAt") - .HasDatabaseName("idx_billing_created_at"); - - b.HasIndex("Status", "DueDate") - .HasDatabaseName("idx_billing_status_duedate") - .HasFilter("\"Status\" IN (0, 2)"); - - b.HasIndex("TenantId", "StatementNo") - .IsUnique(); - - b.HasIndex("TenantId", "Status", "DueDate") - .HasDatabaseName("idx_billing_tenant_status_duedate"); - - b.ToTable("tenant_billing_statements", null, t => - { - t.HasComment("租户账单,用于呈现周期性收费。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantNotification", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("发布通道(站内、邮件、短信等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("通知正文。"); - - b.Property("MetadataJson") - .HasColumnType("text") - .HasComment("附加元数据 JSON。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("租户是否已阅读。"); - - b.Property("SentAt") - .HasColumnType("timestamp with time zone") - .HasComment("推送时间。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("通知重要级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("通知标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Channel", "SentAt"); - - b.ToTable("tenant_notifications", null, t => - { - t.HasComment("面向租户的站内通知或消息推送。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantPackage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("套餐描述,包含适用场景、权益等。"); - - b.Property("FeaturePoliciesJson") - .HasColumnType("text") - .HasComment("权益明细 JSON,记录自定义特性开关。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否仍启用(平台控制)。"); - - b.Property("IsAllowNewTenantPurchase") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否允许新租户购买/选择(仅影响新购)。"); - - b.Property("IsPublicVisible") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否对外可见(展示页/套餐列表可见性)。"); - - b.Property("IsRecommended") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false) - .HasComment("是否推荐展示(运营推荐标识)。"); - - b.Property("MaxAccountCount") - .HasColumnType("integer") - .HasComment("允许创建的最大账号数。"); - - b.Property("MaxDeliveryOrders") - .HasColumnType("integer") - .HasComment("每月可调用的配送单数量上限。"); - - b.Property("MaxSmsCredits") - .HasColumnType("integer") - .HasComment("每月短信额度上限。"); - - b.Property("MaxStorageGb") - .HasColumnType("integer") - .HasComment("存储容量上限(GB)。"); - - b.Property("MaxStoreCount") - .HasColumnType("integer") - .HasComment("允许的最大门店数。"); - - b.Property("MonthlyPrice") - .HasColumnType("numeric") - .HasComment("月付价格,单位:人民币元。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("套餐名称,展示给租户的简称。"); - - b.Property("PackageType") - .HasColumnType("integer") - .HasComment("套餐分类(试用、标准、旗舰等)。"); - - b.Property("PublishStatus") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("发布状态:0=草稿,1=已发布。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("展示排序,数值越小越靠前。"); - - b.PrimitiveCollection("Tags") - .IsRequired() - .HasColumnType("text[]") - .HasComment("套餐标签(用于展示与对比页)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("YearlyPrice") - .HasColumnType("numeric") - .HasComment("年付价格,单位:人民币元。"); - - b.HasKey("Id"); - - b.HasIndex("IsActive", "SortOrder"); - - b.HasIndex("PublishStatus", "IsActive", "IsPublicVisible", "IsAllowNewTenantPurchase", "SortOrder"); - - b.ToTable("tenant_packages", null, t => - { - t.HasComment("平台提供的租户套餐定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantPayment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("支付金额。"); - - b.Property("BillingStatementId") - .HasColumnType("bigint") - .HasComment("关联的账单 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Method") - .HasColumnType("integer") - .HasComment("支付方式。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付时间。"); - - b.Property("ProofUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("支付凭证 URL。"); - - b.Property("RefundReason") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("退款原因。"); - - b.Property("RefundedAt") - .HasColumnType("timestamp with time zone") - .HasComment("退款时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TransactionNo") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("交易号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("VerifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核时间。"); - - b.Property("VerifiedBy") - .HasColumnType("bigint") - .HasComment("审核人 ID(管理员)。"); - - b.HasKey("Id"); - - b.HasIndex("TransactionNo") - .HasDatabaseName("idx_payment_transaction_no") - .HasFilter("\"TransactionNo\" IS NOT NULL"); - - b.HasIndex("BillingStatementId", "PaidAt") - .HasDatabaseName("idx_payment_billing_paidat"); - - b.HasIndex("TenantId", "BillingStatementId"); - - b.ToTable("tenant_payments", null, t => - { - t.HasComment("租户支付记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaPackagePurchase", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiredAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(可选)。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("购买价格。"); - - b.Property("PurchasedAt") - .HasColumnType("timestamp with time zone") - .HasComment("购买时间。"); - - b.Property("QuotaPackageId") - .HasColumnType("bigint") - .HasComment("配额包 ID。"); - - b.Property("QuotaValue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("购买时的配额值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "QuotaPackageId", "PurchasedAt"); - - b.ToTable("tenant_quota_package_purchases", null, t => - { - t.HasComment("租户配额包购买记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaUsage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LastResetAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次重置时间。"); - - b.Property("LimitValue") - .HasColumnType("numeric") - .HasComment("当前配额上限。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型,例如门店数、短信条数等。"); - - b.Property("ResetCycle") - .HasColumnType("text") - .HasComment("配额刷新周期描述(如月、年)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedValue") - .HasColumnType("numeric") - .HasComment("已消耗的数量。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "QuotaType") - .IsUnique(); - - b.ToTable("tenant_quota_usages", null, t => - { - t.HasComment("租户配额使用情况快照。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaUsageHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChangeAmount") - .HasColumnType("numeric") - .HasComment("变更量(可选)。"); - - b.Property("ChangeReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("变更原因(可选)。"); - - b.Property("ChangeType") - .HasColumnType("integer") - .HasComment("变更类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LimitValue") - .HasColumnType("numeric") - .HasComment("限额值(记录时刻的快照)。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型。"); - - b.Property("RecordedAt") - .HasColumnType("timestamp with time zone") - .HasComment("记录时间(UTC)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedValue") - .HasColumnType("numeric") - .HasComment("已使用值(记录时刻的快照)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "RecordedAt"); - - b.HasIndex("TenantId", "QuotaType", "RecordedAt"); - - b.ToTable("tenant_quota_usage_histories", null, t => - { - t.HasComment("租户配额使用历史记录(用于追踪配额上下限与使用量的时间序列变化)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantReviewClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ClaimedAt") - .HasColumnType("timestamp with time zone") - .HasComment("领取时间(UTC)。"); - - b.Property("ClaimedBy") - .HasColumnType("bigint") - .HasComment("领取人用户 ID。"); - - b.Property("ClaimedByName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("领取人名称(展示用快照)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReleasedAt") - .HasColumnType("timestamp with time zone") - .HasComment("释放时间(UTC),未释放时为 null。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("被领取的租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("ClaimedBy"); - - b.HasIndex("TenantId") - .IsUnique() - .HasFilter("\"ReleasedAt\" IS NULL AND \"DeletedAt\" IS NULL"); - - b.ToTable("tenant_review_claims", null, t => - { - t.HasComment("租户入驻审核领取记录(防止多管理员并发审核)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscription", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AutoRenew") - .HasColumnType("boolean") - .HasComment("是否开启自动续费。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("订阅生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("订阅到期时间(UTC)。"); - - b.Property("NextBillingDate") - .HasColumnType("timestamp with time zone") - .HasComment("下一个计费时间,配合自动续费使用。"); - - b.Property("Notes") - .HasColumnType("text") - .HasComment("运营备注信息。"); - - b.Property("ScheduledPackageId") - .HasColumnType("bigint") - .HasComment("若已排期升降配,对应的新套餐 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("订阅当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TenantPackageId") - .HasColumnType("bigint") - .HasComment("当前订阅关联的套餐标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantPackageId"); - - b.ToTable("tenant_subscriptions", null, t => - { - t.HasComment("租户套餐订阅记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscriptionHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasColumnType("numeric") - .HasComment("相关费用。"); - - b.Property("ChangeType") - .HasColumnType("integer") - .HasComment("变更类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Currency") - .HasMaxLength(8) - .HasColumnType("character varying(8)") - .HasComment("币种。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("FromPackageId") - .HasColumnType("bigint") - .HasComment("原套餐 ID。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("租户标识。"); - - b.Property("TenantSubscriptionId") - .HasColumnType("bigint") - .HasComment("对应的订阅 ID。"); - - b.Property("ToPackageId") - .HasColumnType("bigint") - .HasComment("新套餐 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantSubscriptionId"); - - b.ToTable("tenant_subscription_histories", null, t => - { - t.HasComment("租户套餐订阅变更记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantVerificationProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdditionalDataJson") - .HasColumnType("text") - .HasComment("附加资料(JSON)。"); - - b.Property("BankAccountName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("开户名。"); - - b.Property("BankAccountNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("银行账号。"); - - b.Property("BankName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("银行名称。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照编号。"); - - b.Property("BusinessLicenseUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营业执照文件地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LegalPersonIdBackUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证反面。"); - - b.Property("LegalPersonIdFrontUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证正面。"); - - b.Property("LegalPersonIdNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("法人身份证号。"); - - b.Property("LegalPersonName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人姓名。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注。"); - - b.Property("ReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核时间。"); - - b.Property("ReviewedBy") - .HasColumnType("bigint") - .HasComment("审核人 ID。"); - - b.Property("ReviewedByName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("审核人姓名。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("实名状态。"); - - b.Property("SubmittedAt") - .HasColumnType("timestamp with time zone") - .HasComment("提交时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("对应的租户标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId") - .IsUnique(); - - b.ToTable("tenant_verification_profiles", null, t => - { - t.HasComment("租户实名认证资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.HasOne("TakeoutSaaS.Domain.Orders.Entities.Order", null) - .WithMany() - .HasForeignKey("OrderId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251218121053_AddTenantQuotaUsageHistories.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251218121053_AddTenantQuotaUsageHistories.cs deleted file mode 100644 index 9a9fdb4..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251218121053_AddTenantQuotaUsageHistories.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - /// - public partial class AddTenantQuotaUsageHistories : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "tenant_quota_usage_histories", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - QuotaType = table.Column(type: "integer", nullable: false, comment: "配额类型。"), - UsedValue = table.Column(type: "numeric", nullable: false, comment: "已使用值(记录时刻的快照)。"), - LimitValue = table.Column(type: "numeric", nullable: false, comment: "限额值(记录时刻的快照)。"), - RecordedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "记录时间(UTC)。"), - ChangeType = table.Column(type: "integer", nullable: false, comment: "变更类型。"), - ChangeAmount = table.Column(type: "numeric", nullable: true, comment: "变更量(可选)。"), - ChangeReason = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "变更原因(可选)。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_tenant_quota_usage_histories", x => x.Id); - }, - comment: "租户配额使用历史记录(用于追踪配额上下限与使用量的时间序列变化)。"); - - migrationBuilder.CreateIndex( - name: "IX_tenant_quota_usage_histories_TenantId_QuotaType_RecordedAt", - table: "tenant_quota_usage_histories", - columns: new[] { "TenantId", "QuotaType", "RecordedAt" }); - - migrationBuilder.CreateIndex( - name: "IX_tenant_quota_usage_histories_TenantId_RecordedAt", - table: "tenant_quota_usage_histories", - columns: new[] { "TenantId", "RecordedAt" }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "tenant_quota_usage_histories"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251220160000_AddTenantAnnouncementStatusAndPublisher.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251220160000_AddTenantAnnouncementStatusAndPublisher.Designer.cs deleted file mode 100644 index 2692389..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251220160000_AddTenantAnnouncementStatusAndPublisher.Designer.cs +++ /dev/null @@ -1,7298 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Microsoft.EntityFrameworkCore.Migrations; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.App.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - [DbContext(typeof(TakeoutAppDbContext))] - [Migration("20251220160000_AddTenantAnnouncementStatusAndPublisher")] - partial class AddTenantAnnouncementStatusAndPublisher - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricAlertRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionJson") - .IsRequired() - .HasColumnType("text") - .HasComment("触发条件 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Enabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("关联指标。"); - - b.Property("NotificationChannels") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("通知渠道。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("告警级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "Severity"); - - b.ToTable("metric_alert_rules", null, t => - { - t.HasComment("指标告警规则。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricDefinition", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("指标编码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultAggregation") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("默认聚合方式。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("说明。"); - - b.Property("DimensionsJson") - .HasColumnType("text") - .HasComment("维度描述 JSON。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("指标名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("metric_definitions", null, t => - { - t.HasComment("指标定义,描述可观测的数据点。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricSnapshot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DimensionKey") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("维度键(JSON)。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("指标定义 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Value") - .HasPrecision(18, 4) - .HasColumnType("numeric(18,4)") - .HasComment("数值。"); - - b.Property("WindowEnd") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口结束。"); - - b.Property("WindowStart") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口开始。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "DimensionKey", "WindowStart", "WindowEnd") - .IsUnique(); - - b.ToTable("metric_snapshots", null, t => - { - t.HasComment("指标快照,用于大盘展示。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.Coupon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("券码或序列号。"); - - b.Property("CouponTemplateId") - .HasColumnType("bigint") - .HasComment("模板标识。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("发放时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID(已使用时记录)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedAt") - .HasColumnType("timestamp with time zone") - .HasComment("使用时间。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("归属用户。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("coupons", null, t => - { - t.HasComment("用户领取的券。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.CouponTemplate", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowStack") - .HasColumnType("boolean") - .HasComment("是否允许叠加其他优惠。"); - - b.Property("ChannelsJson") - .HasColumnType("text") - .HasComment("发放渠道(JSON)。"); - - b.Property("ClaimedQuantity") - .HasColumnType("integer") - .HasComment("已领取数量。"); - - b.Property("CouponType") - .HasColumnType("integer") - .HasComment("券类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("DiscountCap") - .HasColumnType("numeric") - .HasComment("折扣上限(针对折扣券)。"); - - b.Property("MinimumSpend") - .HasColumnType("numeric") - .HasComment("最低消费门槛。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("模板名称。"); - - b.Property("ProductScopeJson") - .HasColumnType("text") - .HasComment("适用品类或商品范围(JSON)。"); - - b.Property("RelativeValidDays") - .HasColumnType("integer") - .HasComment("有效天数(相对发放时间)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreScopeJson") - .HasColumnType("text") - .HasComment("适用门店 ID 集合(JSON)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TotalQuantity") - .HasColumnType("integer") - .HasComment("总发放数量上限。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ValidFrom") - .HasColumnType("timestamp with time zone") - .HasComment("可用开始时间。"); - - b.Property("ValidTo") - .HasColumnType("timestamp with time zone") - .HasComment("可用结束时间。"); - - b.Property("Value") - .HasColumnType("numeric") - .HasComment("面值或折扣额度。"); - - b.HasKey("Id"); - - b.ToTable("coupon_templates", null, t => - { - t.HasComment("优惠券模板。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.PromotionCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AudienceDescription") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("目标人群描述。"); - - b.Property("BannerUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营销素材(如 banner)。"); - - b.Property("Budget") - .HasColumnType("numeric") - .HasComment("预算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("PromotionType") - .HasColumnType("integer") - .HasComment("活动类型。"); - - b.Property("RulesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("活动规则 JSON。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("活动状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("promotion_campaigns", null, t => - { - t.HasComment("营销活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChatSessionId") - .HasColumnType("bigint") - .HasComment("会话标识。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("消息内容。"); - - b.Property("ContentType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("消息类型(文字/图片/语音等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRead") - .HasColumnType("boolean") - .HasComment("是否已读。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("读取时间。"); - - b.Property("SenderType") - .HasColumnType("integer") - .HasComment("发送方类型。"); - - b.Property("SenderUserId") - .HasColumnType("bigint") - .HasComment("发送方用户 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ChatSessionId", "CreatedAt"); - - b.ToTable("chat_messages", null, t => - { - t.HasComment("会话消息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AgentUserId") - .HasColumnType("bigint") - .HasComment("当前客服员工 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("顾客用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndedAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("IsBotActive") - .HasColumnType("boolean") - .HasComment("是否机器人接待中。"); - - b.Property("SessionCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话编号。"); - - b.Property("StartedAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店(可空为平台)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionCode") - .IsUnique(); - - b.ToTable("chat_sessions", null, t => - { - t.HasComment("客服会话。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.SupportTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AssignedAgentId") - .HasColumnType("bigint") - .HasComment("指派的客服。"); - - b.Property("ClosedAt") - .HasColumnType("timestamp with time zone") - .HasComment("关闭时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("客户用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .IsRequired() - .HasColumnType("text") - .HasComment("工单详情。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单(如有)。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("优先级。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("Subject") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("工单主题。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("工单编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TicketNo") - .IsUnique(); - - b.ToTable("support_tickets", null, t => - { - t.HasComment("客服工单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.TicketComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttachmentsJson") - .HasColumnType("text") - .HasComment("附件 JSON。"); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人 ID。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsInternal") - .HasColumnType("boolean") - .HasComment("是否内部备注。"); - - b.Property("SupportTicketId") - .HasColumnType("bigint") - .HasComment("工单标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SupportTicketId"); - - b.ToTable("ticket_comments", null, t => - { - t.HasComment("工单评论/流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryEvent", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryOrderId") - .HasColumnType("bigint") - .HasComment("配送单标识。"); - - b.Property("EventType") - .HasColumnType("integer") - .HasComment("事件类型。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("事件描述。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始数据 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DeliveryOrderId", "EventType"); - - b.ToTable("delivery_events", null, t => - { - t.HasComment("配送状态事件流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CourierName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("骑手姓名。"); - - b.Property("CourierPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("骑手电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveredAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("DispatchedAt") - .HasColumnType("timestamp with time zone") - .HasComment("下发时间。"); - - b.Property("FailureReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("异常原因。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("获取或设置关联订单 ID。"); - - b.Property("PickedUpAt") - .HasColumnType("timestamp with time zone") - .HasComment("取餐时间。"); - - b.Property("Provider") - .HasColumnType("integer") - .HasComment("配送服务商。"); - - b.Property("ProviderOrderId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方配送单号。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId") - .IsUnique(); - - b.ToTable("delivery_orders", null, t => - { - t.HasComment("配送单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliateOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("推广人标识。"); - - b.Property("BuyerUserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedCommission") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("预计佣金。"); - - b.Property("OrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("订单金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("SettledAt") - .HasColumnType("timestamp with time zone") - .HasComment("结算完成时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "OrderId") - .IsUnique(); - - b.ToTable("affiliate_orders", null, t => - { - t.HasComment("分销订单记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePartner", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChannelType") - .HasColumnType("integer") - .HasComment("渠道类型。"); - - b.Property("CommissionRate") - .HasColumnType("numeric") - .HasComment("分成比例(0-1)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称或渠道名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID(如绑定平台账号)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DisplayName"); - - b.ToTable("affiliate_partners", null, t => - { - t.HasComment("分销/推广合作伙伴。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePayout", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("合作伙伴标识。"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("结算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("打款时间。"); - - b.Property("Period") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("结算周期描述。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "Period") - .IsUnique(); - - b.ToTable("affiliate_payouts", null, t => - { - t.HasComment("佣金结算记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowMakeupCount") - .HasColumnType("integer") - .HasComment("支持补签次数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("活动描述。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("结束日期。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("RewardsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("连签奖励 JSON。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("开始日期。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name"); - - b.ToTable("checkin_campaigns", null, t => - { - t.HasComment("签到活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CheckInCampaignId") - .HasColumnType("bigint") - .HasComment("活动标识。"); - - b.Property("CheckInDate") - .HasColumnType("timestamp with time zone") - .HasComment("签到日期(本地)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsMakeup") - .HasColumnType("boolean") - .HasComment("是否补签。"); - - b.Property("RewardJson") - .IsRequired() - .HasColumnType("text") - .HasComment("获得奖励 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "CheckInCampaignId", "UserId", "CheckInDate") - .IsUnique(); - - b.ToTable("checkin_records", null, t => - { - t.HasComment("用户签到记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsDeleted") - .HasColumnType("boolean") - .HasComment("状态。"); - - b.Property("ParentId") - .HasColumnType("bigint") - .HasComment("父级评论 ID。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "CreatedAt"); - - b.ToTable("community_comments", null, t => - { - t.HasComment("社区评论。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityPost", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("作者用户 ID。"); - - b.Property("CommentCount") - .HasColumnType("integer") - .HasComment("评论数。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LikeCount") - .HasColumnType("integer") - .HasComment("点赞数。"); - - b.Property("MediaJson") - .HasColumnType("text") - .HasComment("媒体资源 JSON。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AuthorUserId", "CreatedAt"); - - b.ToTable("community_posts", null, t => - { - t.HasComment("社区动态。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityReaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态 ID。"); - - b.Property("ReactedAt") - .HasColumnType("timestamp with time zone") - .HasComment("时间戳。"); - - b.Property("ReactionType") - .HasColumnType("integer") - .HasComment("反应类型。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "UserId") - .IsUnique(); - - b.ToTable("community_reactions", null, t => - { - t.HasComment("社区互动反馈。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentCount") - .HasColumnType("integer") - .HasComment("当前已参与人数。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("GroupOrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("拼单编号。"); - - b.Property("GroupPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("拼团价格。"); - - b.Property("LeaderUserId") - .HasColumnType("bigint") - .HasComment("团长用户 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("关联商品或套餐。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("拼团状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("SucceededAt") - .HasColumnType("timestamp with time zone") - .HasComment("成团时间。"); - - b.Property("TargetCount") - .HasColumnType("integer") - .HasComment("成团需要的人数。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderNo") - .IsUnique(); - - b.ToTable("group_orders", null, t => - { - t.HasComment("拼单活动。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupParticipant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GroupOrderId") - .HasColumnType("bigint") - .HasComment("拼单活动标识。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("参与时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("对应订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("参与状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderId", "UserId") - .IsUnique(); - - b.ToTable("group_participants", null, t => - { - t.HasComment("拼单参与者。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryAdjustment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdjustmentType") - .HasColumnType("integer") - .HasComment("调整类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("InventoryItemId") - .HasColumnType("bigint") - .HasComment("对应的库存记录标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("调整数量,正数增加,负数减少。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("原因说明。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "InventoryItemId", "OccurredAt"); - - b.ToTable("inventory_adjustments", null, t => - { - t.HasComment("库存调整记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryBatch", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("ProductionDate") - .HasColumnType("timestamp with time zone") - .HasComment("生产日期。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("入库数量。"); - - b.Property("RemainingQuantity") - .HasColumnType("integer") - .HasComment("剩余数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber") - .IsUnique(); - - b.ToTable("inventory_batches", null, t => - { - t.HasComment("SKU 批次信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchConsumeStrategy") - .HasColumnType("integer") - .HasComment("批次扣减策略。"); - - b.Property("BatchNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号,可为空表示混批。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售商品。"); - - b.Property("IsSoldOut") - .HasColumnType("boolean") - .HasComment("是否标记售罄。"); - - b.Property("Location") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("储位或仓位信息。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单品限购(覆盖商品级 MaxQuantityPerOrder)。"); - - b.Property("PresaleCapacity") - .HasColumnType("integer") - .HasComment("预售名额(上限)。"); - - b.Property("PresaleEndTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售结束时间(UTC)。"); - - b.Property("PresaleLocked") - .HasColumnType("integer") - .HasComment("当前预售已锁定数量。"); - - b.Property("PresaleStartTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售开始时间(UTC)。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("QuantityOnHand") - .HasColumnType("integer") - .HasComment("可用库存。"); - - b.Property("QuantityReserved") - .HasColumnType("integer") - .HasComment("已锁定库存(订单占用)。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("SafetyStock") - .HasColumnType("integer") - .HasComment("安全库存阈值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber"); - - b.ToTable("inventory_items", null, t => - { - t.HasComment("SKU 在门店的库存信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryLockRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("IdempotencyKey") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("幂等键。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售锁定。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU ID。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("锁定数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("锁定状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "IdempotencyKey") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "Status"); - - b.ToTable("inventory_lock_records", null, t => - { - t.HasComment("库存锁定记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberGrowthLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChangeValue") - .HasColumnType("integer") - .HasComment("变动数量。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentValue") - .HasColumnType("integer") - .HasComment("当前成长值。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_growth_logs", null, t => - { - t.HasComment("成长值变动日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberPointLedger", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BalanceAfterChange") - .HasColumnType("integer") - .HasComment("变动后余额。"); - - b.Property("ChangeAmount") - .HasColumnType("integer") - .HasComment("变动数量,可为负值。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(如适用)。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Reason") - .HasColumnType("integer") - .HasComment("变动原因。"); - - b.Property("SourceId") - .HasColumnType("bigint") - .HasComment("来源 ID(订单、活动等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_point_ledgers", null, t => - { - t.HasComment("积分变动流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AvatarUrl") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像。"); - - b.Property("BirthDate") - .HasColumnType("timestamp with time zone") - .HasComment("生日。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GrowthValue") - .HasColumnType("integer") - .HasComment("成长值/经验值。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("注册时间。"); - - b.Property("MemberTierId") - .HasColumnType("bigint") - .HasComment("当前会员等级 ID。"); - - b.Property("Mobile") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("Nickname") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称。"); - - b.Property("PointsBalance") - .HasColumnType("integer") - .HasComment("会员积分余额。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会员状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Mobile") - .IsUnique(); - - b.ToTable("member_profiles", null, t => - { - t.HasComment("会员档案。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberTier", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BenefitsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("等级权益(JSON)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("等级名称。"); - - b.Property("RequiredGrowth") - .HasColumnType("integer") - .HasComment("所需成长值。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("member_tiers", null, t => - { - t.HasComment("会员等级定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.Merchant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("BrandAlias") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("品牌简称或别名。"); - - b.Property("BrandName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("品牌名称(对外展示)。"); - - b.Property("BusinessLicenseImageUrl") - .HasColumnType("text") - .HasComment("营业执照扫描件地址。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照号。"); - - b.Property("Category") - .HasColumnType("text") - .HasComment("品牌所属品类,如火锅、咖啡等。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("联系邮箱。"); - - b.Property("ContactPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在区县。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("入驻时间。"); - - b.Property("LastReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次审核时间。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度信息。"); - - b.Property("LegalPerson") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人或负责人姓名。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("品牌 Logo。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度信息。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注或驳回原因。"); - - b.Property("ServicePhone") - .HasColumnType("text") - .HasComment("客服电话。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("入驻状态。"); - - b.Property("SupportEmail") - .HasColumnType("text") - .HasComment("客服邮箱。"); - - b.Property("TaxNumber") - .HasColumnType("text") - .HasComment("税号/统一社会信用代码。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.ToTable("merchants", null, t => - { - t.HasComment("商户主体信息,承载入驻和资质审核结果。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantAuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("动作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("详情描述。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("商户标识。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId"); - - b.ToTable("merchant_audit_logs", null, t => - { - t.HasComment("商户入驻审核日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("显示顺序,越小越靠前。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否可用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("类目名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("merchant_categories", null, t => - { - t.HasComment("商户可选类目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantContract", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ContractNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("合同编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同结束时间。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("合同文件存储地址。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("SignedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签署时间。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("合同状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TerminatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("终止时间。"); - - b.Property("TerminationReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("终止原因。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "ContractNumber") - .IsUnique(); - - b.ToTable("merchant_contracts", null, t => - { - t.HasComment("商户合同记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantDocument", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DocumentNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("证照编号。"); - - b.Property("DocumentType") - .HasColumnType("integer") - .HasComment("证照类型。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期日期。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("证照文件链接。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签发日期。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Remarks") - .HasColumnType("text") - .HasComment("审核备注或驳回原因。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("审核状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "DocumentType"); - - b.ToTable("merchant_documents", null, t => - { - t.HasComment("商户提交的资质或证照材料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantStaff", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Email") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("邮箱地址。"); - - b.Property("IdentityUserId") - .HasColumnType("bigint") - .HasComment("登录账号 ID(指向统一身份体系)。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("员工姓名。"); - - b.Property("PermissionsJson") - .HasColumnType("text") - .HasComment("自定义权限(JSON)。"); - - b.Property("Phone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("员工角色类型。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("员工状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("可选的关联门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "Phone"); - - b.ToTable("merchant_staff", null, t => - { - t.HasComment("商户员工账号,支持门店维度分配。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.MapLocation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Landmark") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("打车/导航落点描述。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("名称。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店 ID,可空表示独立 POI。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("map_locations", null, t => - { - t.HasComment("地图 POI 信息,用于门店定位和推荐。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.NavigationRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("来源通道(小程序、H5 等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("请求时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TargetApp") - .HasColumnType("integer") - .HasComment("跳转的地图应用。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId", "RequestedAt"); - - b.ToTable("navigation_requests", null, t => - { - t.HasComment("用户发起的导航请求日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("扩展 JSON(规格、加料选项等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品或 SKU 标识。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称快照。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("自定义备注(口味要求)。"); - - b.Property("ShoppingCartId") - .HasColumnType("bigint") - .HasComment("所属购物车标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价快照。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ShoppingCartId"); - - b.ToTable("cart_items", null, t => - { - t.HasComment("购物车条目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItemAddon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CartItemId") - .HasColumnType("bigint") - .HasComment("所属购物车条目。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("OptionId") - .HasColumnType("bigint") - .HasComment("选项 ID(可对应 ProductAddonOption)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("cart_item_addons", null, t => - { - t.HasComment("购物车条目的加料/附加项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CheckoutSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("SessionToken") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话 Token。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.Property("ValidationResultJson") - .IsRequired() - .HasColumnType("text") - .HasComment("校验结果明细 JSON。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionToken") - .IsUnique(); - - b.ToTable("checkout_sessions", null, t => - { - t.HasComment("结账会话,记录校验上下文。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.ShoppingCart", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryPreference") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("履约方式(堂食/自提/配送)缓存。"); - - b.Property("LastModifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次修改时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("购物车状态,包含正常/锁定。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableContext") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌码或场景标识(扫码点餐)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId") - .IsUnique(); - - b.ToTable("shopping_carts", null, t => - { - t.HasComment("用户购物车,按租户/门店隔离。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.Order", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("取消原因。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("下单渠道。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("顾客姓名。"); - - b.Property("CustomerPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("顾客手机号。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryType") - .HasColumnType("integer") - .HasComment("履约类型。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("优惠金额。"); - - b.Property("FinishedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("ItemsAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("商品总额。"); - - b.Property("OrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("订单号。"); - - b.Property("PaidAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付时间。"); - - b.Property("PayableAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额。"); - - b.Property("PaymentStatus") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("QueueNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队号(如有)。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationId") - .HasColumnType("bigint") - .HasComment("预约 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TableNo") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("就餐桌号。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "Status"); - - b.ToTable("orders", null, t => - { - t.HasComment("交易订单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("自定义属性 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("折扣金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品 ID。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("SkuName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("SKU/规格描述。"); - - b.Property("SubTotal") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("小计。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("单位。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("OrderId"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("order_items", null, t => - { - t.HasComment("订单明细。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderStatusHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注信息。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识(可为空表示系统)。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("变更后的状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId", "OccurredAt"); - - b.ToTable("order_status_histories", null, t => - { - t.HasComment("订单状态流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.RefundRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("申请金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("ProcessedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核完成时间。"); - - b.Property("Reason") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("申请原因。"); - - b.Property("RefundNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("退款单号。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("用户提交时间。"); - - b.Property("ReviewNotes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "RefundNo") - .IsUnique(); - - b.ToTable("refund_requests", null, t => - { - t.HasComment("售后/退款申请。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("支付金额。"); - - b.Property("ChannelTransactionId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方渠道单号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Method") - .HasColumnType("integer") - .HasComment("支付方式。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付完成时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始回调内容。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("错误/备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TradeNo") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("平台交易号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("payment_records", null, t => - { - t.HasComment("支付流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRefundRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("退款金额。"); - - b.Property("ChannelRefundId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("渠道退款流水号。"); - - b.Property("CompletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("渠道返回的原始数据 JSON。"); - - b.Property("PaymentRecordId") - .HasColumnType("bigint") - .HasComment("原支付记录标识。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("退款请求时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PaymentRecordId"); - - b.ToTable("payment_refund_records", null, t => - { - t.HasComment("支付渠道退款流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.Product", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CategoryId") - .HasColumnType("bigint") - .HasComment("所属分类。"); - - b.Property("CoverImage") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("主图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("商品描述。"); - - b.Property("EnableDelivery") - .HasColumnType("boolean") - .HasComment("支持配送。"); - - b.Property("EnableDineIn") - .HasColumnType("boolean") - .HasComment("支持堂食。"); - - b.Property("EnablePickup") - .HasColumnType("boolean") - .HasComment("支持自提。"); - - b.Property("GalleryImages") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Gallery 图片逗号分隔。"); - - b.Property("IsFeatured") - .HasColumnType("boolean") - .HasComment("是否热门推荐。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("最大每单限购。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("现价。"); - - b.Property("SpuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("商品编码。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("商品状态。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("库存数量(可选)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("Subtitle") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("副标题/卖点。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("售卖单位(份/杯等)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SpuCode") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("products", null, t => - { - t.HasComment("商品(SPU)信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("MaxSelect") - .HasColumnType("integer") - .HasComment("最大选择数量。"); - - b.Property("MinSelect") - .HasColumnType("integer") - .HasComment("最小选择数量。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "Name"); - - b.ToTable("product_addon_groups", null, t => - { - t.HasComment("加料/做法分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AddonGroupId") - .HasColumnType("bigint") - .HasComment("所属加料分组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选项。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("product_addon_options", null, t => - { - t.HasComment("加料选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称,例如“辣度”“份量”。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型(单选/多选)。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("显示排序。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店,可为空表示所有门店共享。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("product_attribute_groups", null, t => - { - t.HasComment("商品规格/属性分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributeGroupId") - .HasColumnType("bigint") - .HasComment("所属规格组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选中。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AttributeGroupId", "Name") - .IsUnique(); - - b.ToTable("product_attribute_options", null, t => - { - t.HasComment("商品规格选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("分类描述。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分类名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("product_categories", null, t => - { - t.HasComment("商品分类。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductMediaAsset", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Caption") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述或标题。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MediaType") - .HasColumnType("integer") - .HasComment("媒体类型。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品标识。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Url") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("媒资链接。"); - - b.HasKey("Id"); - - b.ToTable("product_media_assets", null, t => - { - t.HasComment("商品媒资素材。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductPricingRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("条件描述(JSON),如会员等级、渠道等。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效结束时间。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("特殊价格。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("RuleType") - .HasColumnType("integer") - .HasComment("策略类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StartTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效开始时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("WeekdaysJson") - .HasColumnType("text") - .HasComment("生效星期(JSON 数组)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "RuleType"); - - b.ToTable("product_pricing_rules", null, t => - { - t.HasComment("商品价格策略,支持会员价/时段价等。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductSku", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("规格属性 JSON(记录选项 ID)。"); - - b.Property("Barcode") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("条形码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("售价。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SkuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("SKU 编码。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("可售库存。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weight") - .HasPrecision(10, 3) - .HasColumnType("numeric(10,3)") - .HasComment("重量(千克)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SkuCode") - .IsUnique(); - - b.ToTable("product_skus", null, t => - { - t.HasComment("商品 SKU,记录具体规格组合价格。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Queues.Entities.QueueTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CalledAt") - .HasColumnType("timestamp with time zone") - .HasComment("叫号时间。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedWaitMinutes") - .HasColumnType("integer") - .HasComment("预计等待分钟。"); - - b.Property("ExpiredAt") - .HasColumnType("timestamp with time zone") - .HasComment("过号时间。"); - - b.Property("PartySize") - .HasColumnType("integer") - .HasComment("就餐人数。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("获取或设置所属门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNumber") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.HasIndex("TenantId", "StoreId", "TicketNumber") - .IsUnique(); - - b.ToTable("queue_tickets", null, t => - { - t.HasComment("排队叫号。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Reservations.Entities.Reservation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CheckInCode") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("核销码/到店码。"); - - b.Property("CheckedInAt") - .HasColumnType("timestamp with time zone") - .HasComment("实际签到时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("客户姓名。"); - - b.Property("CustomerPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PeopleCount") - .HasColumnType("integer") - .HasComment("用餐人数。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("预约号。"); - - b.Property("ReservationTime") - .HasColumnType("timestamp with time zone") - .HasComment("预约时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TablePreference") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌型/标签。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ReservationNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("reservations", null, t => - { - t.HasComment("预约/预订记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.Store", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("Announcement") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("门店公告。"); - - b.Property("BusinessHours") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("门店营业时段描述(备用字符串)。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("门店编码,便于扫码及外部对接。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家或地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("门店海报。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryRadiusKm") - .HasPrecision(6, 2) - .HasColumnType("numeric(6,2)") - .HasComment("默认配送半径(公里)。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("门店描述或公告。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区县信息。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("高德/腾讯地图经度。"); - - b.Property("ManagerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("门店负责人姓名。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("门店名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("门店当前运营状态。"); - - b.Property("SupportsDelivery") - .HasColumnType("boolean") - .HasComment("是否支持配送。"); - - b.Property("SupportsDineIn") - .HasColumnType("boolean") - .HasComment("是否支持堂食。"); - - b.Property("SupportsPickup") - .HasColumnType("boolean") - .HasComment("是否支持自提。"); - - b.Property("SupportsQueueing") - .HasColumnType("boolean") - .HasComment("支持排队叫号。"); - - b.Property("SupportsReservation") - .HasColumnType("boolean") - .HasComment("支持预约。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("门店标签(逗号分隔)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.HasIndex("TenantId", "MerchantId"); - - b.ToTable("stores", null, t => - { - t.HasComment("门店信息,承载营业配置与能力。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreBusinessHour", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CapacityLimit") - .HasColumnType("integer") - .HasComment("最大接待容量或单量限制。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DayOfWeek") - .HasColumnType("integer") - .HasComment("星期几,0 表示周日。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间(本地时间)。"); - - b.Property("HourType") - .HasColumnType("integer") - .HasComment("时段类型(正常营业、休息、预约等)。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间(本地时间)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "DayOfWeek"); - - b.ToTable("store_business_hours", null, t => - { - t.HasComment("门店营业时段配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreDeliveryZone", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("EstimatedMinutes") - .HasColumnType("integer") - .HasComment("预计送达分钟。"); - - b.Property("MinimumOrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("起送价。"); - - b.Property("PolygonGeoJson") - .IsRequired() - .HasColumnType("text") - .HasComment("GeoJSON 表示的多边形范围。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ZoneName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ZoneName"); - - b.ToTable("store_delivery_zones", null, t => - { - t.HasComment("门店配送范围配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreEmployeeShift", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("排班角色。"); - - b.Property("ShiftDate") - .HasColumnType("timestamp with time zone") - .HasComment("班次日期。"); - - b.Property("StaffId") - .HasColumnType("bigint") - .HasComment("员工标识。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ShiftDate", "StaffId") - .IsUnique(); - - b.ToTable("store_employee_shifts", null, t => - { - t.HasComment("门店员工排班记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreHoliday", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Date") - .HasColumnType("timestamp with time zone") - .HasComment("日期。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsClosed") - .HasColumnType("boolean") - .HasComment("是否全天闭店。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("说明内容。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Date") - .IsUnique(); - - b.ToTable("store_holidays", null, t => - { - t.HasComment("门店休息日或特殊营业日。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSetting", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowDaysAhead") - .HasColumnType("integer") - .HasComment("可预约天数(含当天)。"); - - b.Property("AllowToday") - .HasColumnType("boolean") - .HasComment("是否允许当天自提。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultCutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("默认截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单笔自提最大份数。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId") - .IsUnique(); - - b.ToTable("store_pickup_settings", null, t => - { - t.HasComment("门店自提配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSlot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("容量(份数)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("当天结束时间(UTC)。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("档期名称。"); - - b.Property("ReservedCount") - .HasColumnType("integer") - .HasComment("已占用数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("当天开始时间(UTC)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weekdays") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("适用星期(逗号分隔 1-7)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("store_pickup_slots", null, t => - { - t.HasComment("门店自提档期。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTable", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AreaId") - .HasColumnType("bigint") - .HasComment("所在区域 ID。"); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("可容纳人数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("QrCodeUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("桌码二维码地址。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前桌台状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("桌码。"); - - b.Property("Tags") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("桌台标签(堂食、快餐等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "TableCode") - .IsUnique(); - - b.ToTable("store_tables", null, t => - { - t.HasComment("桌台信息与二维码绑定。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTableArea", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("区域描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name") - .IsUnique(); - - b.ToTable("store_table_areas", null, t => - { - t.HasComment("门店桌台区域配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.OperationLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OperationType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作类型:BatchExtend, BatchRemind, StatusChange 等。"); - - b.Property("OperatorId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人ID。"); - - b.Property("OperatorName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("操作人名称。"); - - b.Property("Parameters") - .HasColumnType("text") - .HasComment("操作参数(JSON)。"); - - b.Property("Result") - .HasColumnType("text") - .HasComment("操作结果(JSON)。"); - - b.Property("Success") - .HasColumnType("boolean") - .HasComment("是否成功。"); - - b.Property("TargetIds") - .HasColumnType("text") - .HasComment("目标ID列表(JSON)。"); - - b.Property("TargetType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("目标类型:Subscription, Bill 等。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("CreatedAt"); - - b.HasIndex("OperationType", "CreatedAt"); - - b.ToTable("operation_logs", null, t => - { - t.HasComment("运营操作日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.QuotaPackage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("描述。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否上架。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("配额包名称。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("价格。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型。"); - - b.Property("QuotaValue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配额数值。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("排序。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("QuotaType", "IsActive", "SortOrder"); - - b.ToTable("quota_packages", null, t => - { - t.HasComment("配额包定义(平台提供的可购买配额包)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.Tenant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("text") - .HasComment("详细地址信息。"); - - b.Property("City") - .HasColumnType("text") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("租户短编码,作为跨系统引用的唯一标识。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("主联系人邮箱。"); - - b.Property("ContactName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("主联系人姓名。"); - - b.Property("ContactPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("主联系人电话。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家/地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("品牌海报或封面图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("服务生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("服务到期时间(UTC)。"); - - b.Property("Industry") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所属行业,如餐饮、零售等。"); - - b.Property("LegalEntityName") - .HasColumnType("text") - .HasComment("法人或公司主体名称。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("LOGO 图片地址。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("租户全称或品牌名称。"); - - b.Property("PrimaryOwnerUserId") - .HasColumnType("bigint") - .HasComment("系统内对应的租户所有者账号 ID。"); - - b.Property("Province") - .HasColumnType("text") - .HasComment("所在省份或州。"); - - b.Property("Remarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息,用于运营记录特殊说明。"); - - b.Property("ShortName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("对外展示的简称。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("租户当前状态,涵盖审核、启用、停用等场景。"); - - b.Property("SuspendedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次暂停服务时间。"); - - b.Property("SuspensionReason") - .HasColumnType("text") - .HasComment("暂停或终止的原因说明。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("业务标签集合(逗号分隔)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Website") - .HasColumnType("text") - .HasComment("官网或主要宣传链接。"); - - b.HasKey("Id"); - - b.HasIndex("Code") - .IsUnique(); - - b.HasIndex("ContactPhone") - .IsUnique(); - - b.ToTable("tenants", null, t => - { - t.HasComment("平台租户信息,描述租户的生命周期与基础资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementType") - .HasColumnType("integer") - .HasComment("公告类型。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("公告正文(可为 Markdown/HTML,前端自行渲染)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("失效时间(UTC),为空表示长期有效。"); - - b.Property("PublisherScope") - .HasColumnType("integer") - .HasComment("发布者范围。"); - - b.Property("PublisherUserId") - .HasColumnType("bigint") - .HasComment("发布者用户 ID(平台或租户后台账号)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("公告状态。"); - - b.Property("PublishedAt") - .HasColumnType("timestamp with time zone") - .HasComment("实际发布时间(UTC)。"); - - b.Property("RevokedAt") - .HasColumnType("timestamp with time zone") - .HasComment("撤销时间(UTC)。"); - - b.Property("ScheduledPublishAt") - .HasColumnType("timestamp with time zone") - .HasComment("预定发布时间(UTC)。"); - - b.Property("TargetType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("目标受众类型。"); - - b.Property("TargetParameters") - .HasColumnType("text") - .HasComment("目标受众参数(JSON)。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否启用(已弃用,迁移期保留)。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("展示优先级,数值越大越靠前。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("公告标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AnnouncementType", "IsActive"); - - b.HasIndex("TenantId", "EffectiveFrom", "EffectiveTo"); - - b.HasIndex("TenantId", "Status", "EffectiveFrom"); - - b.HasIndex("Status", "EffectiveFrom") - .HasFilter("\"TenantId\" = 0"); - - b.ToTable("tenant_announcements", null, t => - { - t.HasComment("租户公告。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncementRead", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementId") - .HasColumnType("bigint") - .HasComment("公告 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("已读时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("已读用户 ID(后台账号),为空表示租户级已读。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AnnouncementId", "UserId") - .IsUnique(); - - b.ToTable("tenant_announcement_reads", null, t => - { - t.HasComment("租户公告已读记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("操作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentStatus") - .HasColumnType("integer") - .HasComment("新状态。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("详细描述。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人名称。"); - - b.Property("PreviousStatus") - .HasColumnType("integer") - .HasComment("原状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("关联的租户标识。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("日志标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.ToTable("tenant_audit_logs", null, t => - { - t.HasComment("租户运营审核日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantBillingStatement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AmountDue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额(原始金额)。"); - - b.Property("AmountPaid") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("BillingType") - .HasColumnType("integer") - .HasComment("账单类型(订阅账单/配额包账单/手动账单/续费账单)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Currency") - .IsRequired() - .ValueGeneratedOnAdd() - .HasMaxLength(8) - .HasColumnType("character varying(8)") - .HasDefaultValue("CNY") - .HasComment("货币类型(默认 CNY)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("折扣金额。"); - - b.Property("DueDate") - .HasColumnType("timestamp with time zone") - .HasComment("到期日。"); - - b.Property("LineItemsJson") - .HasColumnType("text") - .HasComment("账单明细 JSON,记录各项费用。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息(如:人工备注、取消原因等)。"); - - b.Property("OverdueNotifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("逾期通知时间。"); - - b.Property("PeriodEnd") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期结束时间。"); - - b.Property("PeriodStart") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期开始时间。"); - - b.Property("ReminderSentAt") - .HasColumnType("timestamp with time zone") - .HasComment("提醒发送时间(续费提醒、逾期提醒等)。"); - - b.Property("StatementNo") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("账单编号,供对账查询。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前付款状态。"); - - b.Property("SubscriptionId") - .HasColumnType("bigint") - .HasComment("关联的订阅 ID(仅当 BillingType 为 Subscription 或 Renewal 时有值)。"); - - b.Property("TaxAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("税费金额。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("CreatedAt") - .HasDatabaseName("idx_billing_created_at"); - - b.HasIndex("Status", "DueDate") - .HasDatabaseName("idx_billing_status_duedate") - .HasFilter("\"Status\" IN (0, 2)"); - - b.HasIndex("TenantId", "StatementNo") - .IsUnique(); - - b.HasIndex("TenantId", "Status", "DueDate") - .HasDatabaseName("idx_billing_tenant_status_duedate"); - - b.ToTable("tenant_billing_statements", null, t => - { - t.HasComment("租户账单,用于呈现周期性收费。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantNotification", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("发布通道(站内、邮件、短信等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("通知正文。"); - - b.Property("MetadataJson") - .HasColumnType("text") - .HasComment("附加元数据 JSON。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("租户是否已阅读。"); - - b.Property("SentAt") - .HasColumnType("timestamp with time zone") - .HasComment("推送时间。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("通知重要级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("通知标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Channel", "SentAt"); - - b.ToTable("tenant_notifications", null, t => - { - t.HasComment("面向租户的站内通知或消息推送。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantPackage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("套餐描述,包含适用场景、权益等。"); - - b.Property("FeaturePoliciesJson") - .HasColumnType("text") - .HasComment("权益明细 JSON,记录自定义特性开关。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否仍启用(平台控制)。"); - - b.Property("IsAllowNewTenantPurchase") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否允许新租户购买/选择(仅影响新购)。"); - - b.Property("IsPublicVisible") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否对外可见(展示页/套餐列表可见性)。"); - - b.Property("IsRecommended") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false) - .HasComment("是否推荐展示(运营推荐标识)。"); - - b.Property("MaxAccountCount") - .HasColumnType("integer") - .HasComment("允许创建的最大账号数。"); - - b.Property("MaxDeliveryOrders") - .HasColumnType("integer") - .HasComment("每月可调用的配送单数量上限。"); - - b.Property("MaxSmsCredits") - .HasColumnType("integer") - .HasComment("每月短信额度上限。"); - - b.Property("MaxStorageGb") - .HasColumnType("integer") - .HasComment("存储容量上限(GB)。"); - - b.Property("MaxStoreCount") - .HasColumnType("integer") - .HasComment("允许的最大门店数。"); - - b.Property("MonthlyPrice") - .HasColumnType("numeric") - .HasComment("月付价格,单位:人民币元。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("套餐名称,展示给租户的简称。"); - - b.Property("PackageType") - .HasColumnType("integer") - .HasComment("套餐分类(试用、标准、旗舰等)。"); - - b.Property("PublishStatus") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("发布状态:0=草稿,1=已发布。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("展示排序,数值越小越靠前。"); - - b.PrimitiveCollection("Tags") - .IsRequired() - .HasColumnType("text[]") - .HasComment("套餐标签(用于展示与对比页)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("YearlyPrice") - .HasColumnType("numeric") - .HasComment("年付价格,单位:人民币元。"); - - b.HasKey("Id"); - - b.HasIndex("IsActive", "SortOrder"); - - b.HasIndex("PublishStatus", "IsActive", "IsPublicVisible", "IsAllowNewTenantPurchase", "SortOrder"); - - b.ToTable("tenant_packages", null, t => - { - t.HasComment("平台提供的租户套餐定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantPayment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("支付金额。"); - - b.Property("BillingStatementId") - .HasColumnType("bigint") - .HasComment("关联的账单 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Method") - .HasColumnType("integer") - .HasComment("支付方式。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付时间。"); - - b.Property("ProofUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("支付凭证 URL。"); - - b.Property("RefundReason") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("退款原因。"); - - b.Property("RefundedAt") - .HasColumnType("timestamp with time zone") - .HasComment("退款时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TransactionNo") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("交易号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("VerifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核时间。"); - - b.Property("VerifiedBy") - .HasColumnType("bigint") - .HasComment("审核人 ID(管理员)。"); - - b.HasKey("Id"); - - b.HasIndex("TransactionNo") - .HasDatabaseName("idx_payment_transaction_no") - .HasFilter("\"TransactionNo\" IS NOT NULL"); - - b.HasIndex("BillingStatementId", "PaidAt") - .HasDatabaseName("idx_payment_billing_paidat"); - - b.HasIndex("TenantId", "BillingStatementId"); - - b.ToTable("tenant_payments", null, t => - { - t.HasComment("租户支付记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaPackagePurchase", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiredAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(可选)。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("购买价格。"); - - b.Property("PurchasedAt") - .HasColumnType("timestamp with time zone") - .HasComment("购买时间。"); - - b.Property("QuotaPackageId") - .HasColumnType("bigint") - .HasComment("配额包 ID。"); - - b.Property("QuotaValue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("购买时的配额值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "QuotaPackageId", "PurchasedAt"); - - b.ToTable("tenant_quota_package_purchases", null, t => - { - t.HasComment("租户配额包购买记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaUsage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LastResetAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次重置时间。"); - - b.Property("LimitValue") - .HasColumnType("numeric") - .HasComment("当前配额上限。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型,例如门店数、短信条数等。"); - - b.Property("ResetCycle") - .HasColumnType("text") - .HasComment("配额刷新周期描述(如月、年)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedValue") - .HasColumnType("numeric") - .HasComment("已消耗的数量。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "QuotaType") - .IsUnique(); - - b.ToTable("tenant_quota_usages", null, t => - { - t.HasComment("租户配额使用情况快照。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaUsageHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChangeAmount") - .HasColumnType("numeric") - .HasComment("变更量(可选)。"); - - b.Property("ChangeReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("变更原因(可选)。"); - - b.Property("ChangeType") - .HasColumnType("integer") - .HasComment("变更类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LimitValue") - .HasColumnType("numeric") - .HasComment("限额值(记录时刻的快照)。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型。"); - - b.Property("RecordedAt") - .HasColumnType("timestamp with time zone") - .HasComment("记录时间(UTC)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedValue") - .HasColumnType("numeric") - .HasComment("已使用值(记录时刻的快照)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "RecordedAt"); - - b.HasIndex("TenantId", "QuotaType", "RecordedAt"); - - b.ToTable("tenant_quota_usage_histories", null, t => - { - t.HasComment("租户配额使用历史记录(用于追踪配额上下限与使用量的时间序列变化)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantReviewClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ClaimedAt") - .HasColumnType("timestamp with time zone") - .HasComment("领取时间(UTC)。"); - - b.Property("ClaimedBy") - .HasColumnType("bigint") - .HasComment("领取人用户 ID。"); - - b.Property("ClaimedByName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("领取人名称(展示用快照)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReleasedAt") - .HasColumnType("timestamp with time zone") - .HasComment("释放时间(UTC),未释放时为 null。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("被领取的租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("ClaimedBy"); - - b.HasIndex("TenantId") - .IsUnique() - .HasFilter("\"ReleasedAt\" IS NULL AND \"DeletedAt\" IS NULL"); - - b.ToTable("tenant_review_claims", null, t => - { - t.HasComment("租户入驻审核领取记录(防止多管理员并发审核)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscription", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AutoRenew") - .HasColumnType("boolean") - .HasComment("是否开启自动续费。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("订阅生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("订阅到期时间(UTC)。"); - - b.Property("NextBillingDate") - .HasColumnType("timestamp with time zone") - .HasComment("下一个计费时间,配合自动续费使用。"); - - b.Property("Notes") - .HasColumnType("text") - .HasComment("运营备注信息。"); - - b.Property("ScheduledPackageId") - .HasColumnType("bigint") - .HasComment("若已排期升降配,对应的新套餐 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("订阅当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TenantPackageId") - .HasColumnType("bigint") - .HasComment("当前订阅关联的套餐标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantPackageId"); - - b.ToTable("tenant_subscriptions", null, t => - { - t.HasComment("租户套餐订阅记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscriptionHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasColumnType("numeric") - .HasComment("相关费用。"); - - b.Property("ChangeType") - .HasColumnType("integer") - .HasComment("变更类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Currency") - .HasMaxLength(8) - .HasColumnType("character varying(8)") - .HasComment("币种。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("FromPackageId") - .HasColumnType("bigint") - .HasComment("原套餐 ID。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("租户标识。"); - - b.Property("TenantSubscriptionId") - .HasColumnType("bigint") - .HasComment("对应的订阅 ID。"); - - b.Property("ToPackageId") - .HasColumnType("bigint") - .HasComment("新套餐 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantSubscriptionId"); - - b.ToTable("tenant_subscription_histories", null, t => - { - t.HasComment("租户套餐订阅变更记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantVerificationProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdditionalDataJson") - .HasColumnType("text") - .HasComment("附加资料(JSON)。"); - - b.Property("BankAccountName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("开户名。"); - - b.Property("BankAccountNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("银行账号。"); - - b.Property("BankName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("银行名称。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照编号。"); - - b.Property("BusinessLicenseUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营业执照文件地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LegalPersonIdBackUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证反面。"); - - b.Property("LegalPersonIdFrontUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证正面。"); - - b.Property("LegalPersonIdNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("法人身份证号。"); - - b.Property("LegalPersonName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人姓名。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注。"); - - b.Property("ReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核时间。"); - - b.Property("ReviewedBy") - .HasColumnType("bigint") - .HasComment("审核人 ID。"); - - b.Property("ReviewedByName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("审核人姓名。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("实名状态。"); - - b.Property("SubmittedAt") - .HasColumnType("timestamp with time zone") - .HasComment("提交时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("对应的租户标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId") - .IsUnique(); - - b.ToTable("tenant_verification_profiles", null, t => - { - t.HasComment("租户实名认证资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.HasOne("TakeoutSaaS.Domain.Orders.Entities.Order", null) - .WithMany() - .HasForeignKey("OrderId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} - diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251220160000_AddTenantAnnouncementStatusAndPublisher.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251220160000_AddTenantAnnouncementStatusAndPublisher.cs deleted file mode 100644 index 4839ea5..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251220160000_AddTenantAnnouncementStatusAndPublisher.cs +++ /dev/null @@ -1,146 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - /// - public partial class AddTenantAnnouncementStatusAndPublisher : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "PublisherScope", - table: "tenant_announcements", - type: "integer", - nullable: false, - defaultValue: 0, - comment: "发布者范围。"); - - migrationBuilder.AddColumn( - name: "PublisherUserId", - table: "tenant_announcements", - type: "bigint", - nullable: true, - comment: "发布者用户 ID(平台或租户后台账号)。"); - - migrationBuilder.AddColumn( - name: "Status", - table: "tenant_announcements", - type: "integer", - nullable: false, - defaultValue: 0, - comment: "公告状态。"); - - migrationBuilder.AddColumn( - name: "PublishedAt", - table: "tenant_announcements", - type: "timestamp with time zone", - nullable: true, - comment: "实际发布时间(UTC)。"); - - migrationBuilder.AddColumn( - name: "RevokedAt", - table: "tenant_announcements", - type: "timestamp with time zone", - nullable: true, - comment: "撤销时间(UTC)。"); - - migrationBuilder.AddColumn( - name: "ScheduledPublishAt", - table: "tenant_announcements", - type: "timestamp with time zone", - nullable: true, - comment: "预定发布时间(UTC)。"); - - migrationBuilder.AddColumn( - name: "TargetType", - table: "tenant_announcements", - type: "character varying(64)", - maxLength: 64, - nullable: false, - defaultValue: "", - comment: "目标受众类型。"); - - migrationBuilder.AddColumn( - name: "TargetParameters", - table: "tenant_announcements", - type: "text", - nullable: true, - comment: "目标受众参数(JSON)。"); - - migrationBuilder.AddColumn( - name: "RowVersion", - table: "tenant_announcements", - type: "bytea", - rowVersion: true, - nullable: false, - defaultValue: new byte[0], - comment: "并发控制字段。"); - - migrationBuilder.Sql( - "UPDATE tenant_announcements SET \"Status\" = CASE WHEN \"IsActive\" THEN 1 ELSE 0 END;"); - - migrationBuilder.CreateIndex( - name: "IX_tenant_announcements_TenantId_Status_EffectiveFrom", - table: "tenant_announcements", - columns: new[] { "TenantId", "Status", "EffectiveFrom" }); - - migrationBuilder.CreateIndex( - name: "IX_tenant_announcements_Status_EffectiveFrom_Platform", - table: "tenant_announcements", - columns: new[] { "Status", "EffectiveFrom" }, - filter: "\"TenantId\" = 0"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_tenant_announcements_TenantId_Status_EffectiveFrom", - table: "tenant_announcements"); - - migrationBuilder.DropIndex( - name: "IX_tenant_announcements_Status_EffectiveFrom_Platform", - table: "tenant_announcements"); - - migrationBuilder.DropColumn( - name: "PublisherScope", - table: "tenant_announcements"); - - migrationBuilder.DropColumn( - name: "PublisherUserId", - table: "tenant_announcements"); - - migrationBuilder.DropColumn( - name: "Status", - table: "tenant_announcements"); - - migrationBuilder.DropColumn( - name: "PublishedAt", - table: "tenant_announcements"); - - migrationBuilder.DropColumn( - name: "RevokedAt", - table: "tenant_announcements"); - - migrationBuilder.DropColumn( - name: "ScheduledPublishAt", - table: "tenant_announcements"); - - migrationBuilder.DropColumn( - name: "TargetType", - table: "tenant_announcements"); - - migrationBuilder.DropColumn( - name: "TargetParameters", - table: "tenant_announcements"); - - migrationBuilder.DropColumn( - name: "RowVersion", - table: "tenant_announcements"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251225090000_AddTenantAnnouncementRowVersionTrigger.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251225090000_AddTenantAnnouncementRowVersionTrigger.cs deleted file mode 100644 index 8dfaf44..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251225090000_AddTenantAnnouncementRowVersionTrigger.cs +++ /dev/null @@ -1,54 +0,0 @@ -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using TakeoutSaaS.Infrastructure.App.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - /// - [DbContext(typeof(TakeoutAppDbContext))] - [Migration("20251225090000_AddTenantAnnouncementRowVersionTrigger")] - public partial class AddTenantAnnouncementRowVersionTrigger : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.Sql( - """ - CREATE OR REPLACE FUNCTION public.set_tenant_announcement_row_version() - RETURNS trigger AS $$ - BEGIN - NEW."RowVersion" = decode(md5(random()::text || clock_timestamp()::text), 'hex'); - RETURN NEW; - END; - $$ LANGUAGE plpgsql; - """); - - migrationBuilder.Sql( - """ - DROP TRIGGER IF EXISTS trg_tenant_announcements_row_version ON tenant_announcements; - CREATE TRIGGER trg_tenant_announcements_row_version - BEFORE INSERT OR UPDATE ON tenant_announcements - FOR EACH ROW EXECUTE FUNCTION public.set_tenant_announcement_row_version(); - """); - - migrationBuilder.Sql( - """ - UPDATE tenant_announcements - SET "RowVersion" = decode(md5(random()::text || clock_timestamp()::text), 'hex') - WHERE "RowVersion" IS NULL OR octet_length("RowVersion") = 0; - """); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.Sql( - """ - DROP TRIGGER IF EXISTS trg_tenant_announcements_row_version ON tenant_announcements; - DROP FUNCTION IF EXISTS public.set_tenant_announcement_row_version(); - """); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251229071911_AddMerchantManagement.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251229071911_AddMerchantManagement.Designer.cs deleted file mode 100644 index 36c3016..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251229071911_AddMerchantManagement.Designer.cs +++ /dev/null @@ -1,7080 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.App.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - [DbContext(typeof(TakeoutAppDbContext))] - [Migration("20251229071911_AddMerchantManagement")] - partial class AddMerchantManagement - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.1") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricAlertRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionJson") - .IsRequired() - .HasColumnType("text") - .HasComment("触发条件 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Enabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("关联指标。"); - - b.Property("NotificationChannels") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("通知渠道。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("告警级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "Severity"); - - b.ToTable("metric_alert_rules", null, t => - { - t.HasComment("指标告警规则。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricDefinition", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("指标编码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultAggregation") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("默认聚合方式。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("说明。"); - - b.Property("DimensionsJson") - .HasColumnType("text") - .HasComment("维度描述 JSON。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("指标名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("metric_definitions", null, t => - { - t.HasComment("指标定义,描述可观测的数据点。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricSnapshot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DimensionKey") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("维度键(JSON)。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("指标定义 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Value") - .HasPrecision(18, 4) - .HasColumnType("numeric(18,4)") - .HasComment("数值。"); - - b.Property("WindowEnd") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口结束。"); - - b.Property("WindowStart") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口开始。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "DimensionKey", "WindowStart", "WindowEnd") - .IsUnique(); - - b.ToTable("metric_snapshots", null, t => - { - t.HasComment("指标快照,用于大盘展示。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.Coupon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("券码或序列号。"); - - b.Property("CouponTemplateId") - .HasColumnType("bigint") - .HasComment("模板标识。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("发放时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID(已使用时记录)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedAt") - .HasColumnType("timestamp with time zone") - .HasComment("使用时间。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("归属用户。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("coupons", null, t => - { - t.HasComment("用户领取的券。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.CouponTemplate", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowStack") - .HasColumnType("boolean") - .HasComment("是否允许叠加其他优惠。"); - - b.Property("ChannelsJson") - .HasColumnType("text") - .HasComment("发放渠道(JSON)。"); - - b.Property("ClaimedQuantity") - .HasColumnType("integer") - .HasComment("已领取数量。"); - - b.Property("CouponType") - .HasColumnType("integer") - .HasComment("券类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("DiscountCap") - .HasColumnType("numeric") - .HasComment("折扣上限(针对折扣券)。"); - - b.Property("MinimumSpend") - .HasColumnType("numeric") - .HasComment("最低消费门槛。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("模板名称。"); - - b.Property("ProductScopeJson") - .HasColumnType("text") - .HasComment("适用品类或商品范围(JSON)。"); - - b.Property("RelativeValidDays") - .HasColumnType("integer") - .HasComment("有效天数(相对发放时间)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreScopeJson") - .HasColumnType("text") - .HasComment("适用门店 ID 集合(JSON)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TotalQuantity") - .HasColumnType("integer") - .HasComment("总发放数量上限。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ValidFrom") - .HasColumnType("timestamp with time zone") - .HasComment("可用开始时间。"); - - b.Property("ValidTo") - .HasColumnType("timestamp with time zone") - .HasComment("可用结束时间。"); - - b.Property("Value") - .HasColumnType("numeric") - .HasComment("面值或折扣额度。"); - - b.HasKey("Id"); - - b.ToTable("coupon_templates", null, t => - { - t.HasComment("优惠券模板。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.PromotionCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AudienceDescription") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("目标人群描述。"); - - b.Property("BannerUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营销素材(如 banner)。"); - - b.Property("Budget") - .HasColumnType("numeric") - .HasComment("预算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("PromotionType") - .HasColumnType("integer") - .HasComment("活动类型。"); - - b.Property("RulesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("活动规则 JSON。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("活动状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("promotion_campaigns", null, t => - { - t.HasComment("营销活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChatSessionId") - .HasColumnType("bigint") - .HasComment("会话标识。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("消息内容。"); - - b.Property("ContentType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("消息类型(文字/图片/语音等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRead") - .HasColumnType("boolean") - .HasComment("是否已读。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("读取时间。"); - - b.Property("SenderType") - .HasColumnType("integer") - .HasComment("发送方类型。"); - - b.Property("SenderUserId") - .HasColumnType("bigint") - .HasComment("发送方用户 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ChatSessionId", "CreatedAt"); - - b.ToTable("chat_messages", null, t => - { - t.HasComment("会话消息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AgentUserId") - .HasColumnType("bigint") - .HasComment("当前客服员工 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("顾客用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndedAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("IsBotActive") - .HasColumnType("boolean") - .HasComment("是否机器人接待中。"); - - b.Property("SessionCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话编号。"); - - b.Property("StartedAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店(可空为平台)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionCode") - .IsUnique(); - - b.ToTable("chat_sessions", null, t => - { - t.HasComment("客服会话。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.SupportTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AssignedAgentId") - .HasColumnType("bigint") - .HasComment("指派的客服。"); - - b.Property("ClosedAt") - .HasColumnType("timestamp with time zone") - .HasComment("关闭时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("客户用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .IsRequired() - .HasColumnType("text") - .HasComment("工单详情。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单(如有)。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("优先级。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("Subject") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("工单主题。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("工单编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TicketNo") - .IsUnique(); - - b.ToTable("support_tickets", null, t => - { - t.HasComment("客服工单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.TicketComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttachmentsJson") - .HasColumnType("text") - .HasComment("附件 JSON。"); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人 ID。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsInternal") - .HasColumnType("boolean") - .HasComment("是否内部备注。"); - - b.Property("SupportTicketId") - .HasColumnType("bigint") - .HasComment("工单标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SupportTicketId"); - - b.ToTable("ticket_comments", null, t => - { - t.HasComment("工单评论/流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryEvent", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryOrderId") - .HasColumnType("bigint") - .HasComment("配送单标识。"); - - b.Property("EventType") - .HasColumnType("integer") - .HasComment("事件类型。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("事件描述。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始数据 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DeliveryOrderId", "EventType"); - - b.ToTable("delivery_events", null, t => - { - t.HasComment("配送状态事件流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CourierName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("骑手姓名。"); - - b.Property("CourierPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("骑手电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveredAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("DispatchedAt") - .HasColumnType("timestamp with time zone") - .HasComment("下发时间。"); - - b.Property("FailureReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("异常原因。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("获取或设置关联订单 ID。"); - - b.Property("PickedUpAt") - .HasColumnType("timestamp with time zone") - .HasComment("取餐时间。"); - - b.Property("Provider") - .HasColumnType("integer") - .HasComment("配送服务商。"); - - b.Property("ProviderOrderId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方配送单号。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId") - .IsUnique(); - - b.ToTable("delivery_orders", null, t => - { - t.HasComment("配送单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliateOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("推广人标识。"); - - b.Property("BuyerUserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedCommission") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("预计佣金。"); - - b.Property("OrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("订单金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("SettledAt") - .HasColumnType("timestamp with time zone") - .HasComment("结算完成时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "OrderId") - .IsUnique(); - - b.ToTable("affiliate_orders", null, t => - { - t.HasComment("分销订单记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePartner", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChannelType") - .HasColumnType("integer") - .HasComment("渠道类型。"); - - b.Property("CommissionRate") - .HasColumnType("numeric") - .HasComment("分成比例(0-1)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称或渠道名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID(如绑定平台账号)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DisplayName"); - - b.ToTable("affiliate_partners", null, t => - { - t.HasComment("分销/推广合作伙伴。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePayout", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("合作伙伴标识。"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("结算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("打款时间。"); - - b.Property("Period") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("结算周期描述。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "Period") - .IsUnique(); - - b.ToTable("affiliate_payouts", null, t => - { - t.HasComment("佣金结算记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowMakeupCount") - .HasColumnType("integer") - .HasComment("支持补签次数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("活动描述。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("结束日期。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("RewardsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("连签奖励 JSON。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("开始日期。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name"); - - b.ToTable("checkin_campaigns", null, t => - { - t.HasComment("签到活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CheckInCampaignId") - .HasColumnType("bigint") - .HasComment("活动标识。"); - - b.Property("CheckInDate") - .HasColumnType("timestamp with time zone") - .HasComment("签到日期(本地)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsMakeup") - .HasColumnType("boolean") - .HasComment("是否补签。"); - - b.Property("RewardJson") - .IsRequired() - .HasColumnType("text") - .HasComment("获得奖励 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "CheckInCampaignId", "UserId", "CheckInDate") - .IsUnique(); - - b.ToTable("checkin_records", null, t => - { - t.HasComment("用户签到记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsDeleted") - .HasColumnType("boolean") - .HasComment("状态。"); - - b.Property("ParentId") - .HasColumnType("bigint") - .HasComment("父级评论 ID。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "CreatedAt"); - - b.ToTable("community_comments", null, t => - { - t.HasComment("社区评论。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityPost", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("作者用户 ID。"); - - b.Property("CommentCount") - .HasColumnType("integer") - .HasComment("评论数。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LikeCount") - .HasColumnType("integer") - .HasComment("点赞数。"); - - b.Property("MediaJson") - .HasColumnType("text") - .HasComment("媒体资源 JSON。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AuthorUserId", "CreatedAt"); - - b.ToTable("community_posts", null, t => - { - t.HasComment("社区动态。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityReaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态 ID。"); - - b.Property("ReactedAt") - .HasColumnType("timestamp with time zone") - .HasComment("时间戳。"); - - b.Property("ReactionType") - .HasColumnType("integer") - .HasComment("反应类型。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "UserId") - .IsUnique(); - - b.ToTable("community_reactions", null, t => - { - t.HasComment("社区互动反馈。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentCount") - .HasColumnType("integer") - .HasComment("当前已参与人数。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("GroupOrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("拼单编号。"); - - b.Property("GroupPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("拼团价格。"); - - b.Property("LeaderUserId") - .HasColumnType("bigint") - .HasComment("团长用户 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("关联商品或套餐。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("拼团状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("SucceededAt") - .HasColumnType("timestamp with time zone") - .HasComment("成团时间。"); - - b.Property("TargetCount") - .HasColumnType("integer") - .HasComment("成团需要的人数。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderNo") - .IsUnique(); - - b.ToTable("group_orders", null, t => - { - t.HasComment("拼单活动。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupParticipant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GroupOrderId") - .HasColumnType("bigint") - .HasComment("拼单活动标识。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("参与时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("对应订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("参与状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderId", "UserId") - .IsUnique(); - - b.ToTable("group_participants", null, t => - { - t.HasComment("拼单参与者。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryAdjustment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdjustmentType") - .HasColumnType("integer") - .HasComment("调整类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("InventoryItemId") - .HasColumnType("bigint") - .HasComment("对应的库存记录标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("调整数量,正数增加,负数减少。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("原因说明。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "InventoryItemId", "OccurredAt"); - - b.ToTable("inventory_adjustments", null, t => - { - t.HasComment("库存调整记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryBatch", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("ProductionDate") - .HasColumnType("timestamp with time zone") - .HasComment("生产日期。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("入库数量。"); - - b.Property("RemainingQuantity") - .HasColumnType("integer") - .HasComment("剩余数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber") - .IsUnique(); - - b.ToTable("inventory_batches", null, t => - { - t.HasComment("SKU 批次信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchConsumeStrategy") - .HasColumnType("integer") - .HasComment("批次扣减策略。"); - - b.Property("BatchNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号,可为空表示混批。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售商品。"); - - b.Property("IsSoldOut") - .HasColumnType("boolean") - .HasComment("是否标记售罄。"); - - b.Property("Location") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("储位或仓位信息。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单品限购(覆盖商品级 MaxQuantityPerOrder)。"); - - b.Property("PresaleCapacity") - .HasColumnType("integer") - .HasComment("预售名额(上限)。"); - - b.Property("PresaleEndTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售结束时间(UTC)。"); - - b.Property("PresaleLocked") - .HasColumnType("integer") - .HasComment("当前预售已锁定数量。"); - - b.Property("PresaleStartTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售开始时间(UTC)。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("QuantityOnHand") - .HasColumnType("integer") - .HasComment("可用库存。"); - - b.Property("QuantityReserved") - .HasColumnType("integer") - .HasComment("已锁定库存(订单占用)。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("SafetyStock") - .HasColumnType("integer") - .HasComment("安全库存阈值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber"); - - b.ToTable("inventory_items", null, t => - { - t.HasComment("SKU 在门店的库存信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryLockRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("IdempotencyKey") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("幂等键。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售锁定。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU ID。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("锁定数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("锁定状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "IdempotencyKey") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "Status"); - - b.ToTable("inventory_lock_records", null, t => - { - t.HasComment("库存锁定记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberPointLedger", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BalanceAfterChange") - .HasColumnType("integer") - .HasComment("变动后余额。"); - - b.Property("ChangeAmount") - .HasColumnType("integer") - .HasComment("变动数量,可为负值。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(如适用)。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Reason") - .HasColumnType("integer") - .HasComment("变动原因。"); - - b.Property("SourceId") - .HasColumnType("bigint") - .HasComment("来源 ID(订单、活动等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_point_ledgers", null, t => - { - t.HasComment("积分变动流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AvatarUrl") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像。"); - - b.Property("BirthDate") - .HasColumnType("timestamp with time zone") - .HasComment("生日。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GrowthValue") - .HasColumnType("integer") - .HasComment("成长值/经验值。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("注册时间。"); - - b.Property("MemberTierId") - .HasColumnType("bigint") - .HasComment("当前会员等级 ID。"); - - b.Property("Mobile") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("Nickname") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称。"); - - b.Property("PointsBalance") - .HasColumnType("integer") - .HasComment("会员积分余额。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会员状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Mobile") - .IsUnique(); - - b.ToTable("member_profiles", null, t => - { - t.HasComment("会员档案。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberTier", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BenefitsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("等级权益(JSON)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("等级名称。"); - - b.Property("RequiredGrowth") - .HasColumnType("integer") - .HasComment("所需成长值。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("member_tiers", null, t => - { - t.HasComment("会员等级定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.Merchant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("ApprovedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核通过时间。"); - - b.Property("ApprovedBy") - .HasColumnType("bigint") - .HasComment("审核通过人。"); - - b.Property("BrandAlias") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("品牌简称或别名。"); - - b.Property("BrandName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("品牌名称(对外展示)。"); - - b.Property("BusinessLicenseImageUrl") - .HasColumnType("text") - .HasComment("营业执照扫描件地址。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照号。"); - - b.Property("Category") - .HasColumnType("text") - .HasComment("品牌所属品类,如火锅、咖啡等。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("ClaimExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("领取过期时间。"); - - b.Property("ClaimedAt") - .HasColumnType("timestamp with time zone") - .HasComment("领取时间。"); - - b.Property("ClaimedBy") - .HasColumnType("bigint") - .HasComment("当前领取人。"); - - b.Property("ClaimedByName") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasComment("当前领取人姓名。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("联系邮箱。"); - - b.Property("ContactPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在区县。"); - - b.Property("FrozenAt") - .HasColumnType("timestamp with time zone") - .HasComment("冻结时间。"); - - b.Property("FrozenReason") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("冻结原因。"); - - b.Property("IsFrozen") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false) - .HasComment("是否冻结业务。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("入驻时间。"); - - b.Property("LastReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次审核时间。"); - - b.Property("LastReviewedBy") - .HasColumnType("bigint") - .HasComment("最近一次审核人。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度信息。"); - - b.Property("LegalPerson") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人或负责人姓名。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("品牌 Logo。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度信息。"); - - b.Property("OperatingMode") - .HasColumnType("integer") - .HasComment("经营模式(同一主体/不同主体)。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注或驳回原因。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制版本。"); - - b.Property("ServicePhone") - .HasColumnType("text") - .HasComment("客服电话。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("入驻状态。"); - - b.Property("SupportEmail") - .HasColumnType("text") - .HasComment("客服邮箱。"); - - b.Property("TaxNumber") - .HasColumnType("text") - .HasComment("税号/统一社会信用代码。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("ClaimedBy"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Status"); - - b.ToTable("merchants", null, t => - { - t.HasComment("商户主体信息,承载入驻和资质审核结果。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("显示顺序,越小越靠前。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否可用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("类目名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("merchant_categories", null, t => - { - t.HasComment("商户可选类目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantContract", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ContractNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("合同编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同结束时间。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("合同文件存储地址。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("SignedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签署时间。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("合同状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TerminatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("终止时间。"); - - b.Property("TerminationReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("终止原因。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "ContractNumber") - .IsUnique(); - - b.ToTable("merchant_contracts", null, t => - { - t.HasComment("商户合同记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantDocument", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DocumentNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("证照编号。"); - - b.Property("DocumentType") - .HasColumnType("integer") - .HasComment("证照类型。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期日期。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("证照文件链接。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签发日期。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Remarks") - .HasColumnType("text") - .HasComment("审核备注或驳回原因。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("审核状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "DocumentType"); - - b.ToTable("merchant_documents", null, t => - { - t.HasComment("商户提交的资质或证照材料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantStaff", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Email") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("邮箱地址。"); - - b.Property("IdentityUserId") - .HasColumnType("bigint") - .HasComment("登录账号 ID(指向统一身份体系)。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("员工姓名。"); - - b.Property("PermissionsJson") - .HasColumnType("text") - .HasComment("自定义权限(JSON)。"); - - b.Property("Phone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("员工角色类型。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("员工状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("可选的关联门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "Phone"); - - b.ToTable("merchant_staff", null, t => - { - t.HasComment("商户员工账号,支持门店维度分配。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.MapLocation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Landmark") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("打车/导航落点描述。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("名称。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店 ID,可空表示独立 POI。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("map_locations", null, t => - { - t.HasComment("地图 POI 信息,用于门店定位和推荐。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.NavigationRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("来源通道(小程序、H5 等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("请求时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TargetApp") - .HasColumnType("integer") - .HasComment("跳转的地图应用。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId", "RequestedAt"); - - b.ToTable("navigation_requests", null, t => - { - t.HasComment("用户发起的导航请求日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("扩展 JSON(规格、加料选项等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品或 SKU 标识。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称快照。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("自定义备注(口味要求)。"); - - b.Property("ShoppingCartId") - .HasColumnType("bigint") - .HasComment("所属购物车标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价快照。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ShoppingCartId"); - - b.ToTable("cart_items", null, t => - { - t.HasComment("购物车条目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItemAddon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CartItemId") - .HasColumnType("bigint") - .HasComment("所属购物车条目。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("OptionId") - .HasColumnType("bigint") - .HasComment("选项 ID(可对应 ProductAddonOption)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("cart_item_addons", null, t => - { - t.HasComment("购物车条目的加料/附加项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CheckoutSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("SessionToken") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话 Token。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.Property("ValidationResultJson") - .IsRequired() - .HasColumnType("text") - .HasComment("校验结果明细 JSON。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionToken") - .IsUnique(); - - b.ToTable("checkout_sessions", null, t => - { - t.HasComment("结账会话,记录校验上下文。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.ShoppingCart", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryPreference") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("履约方式(堂食/自提/配送)缓存。"); - - b.Property("LastModifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次修改时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("购物车状态,包含正常/锁定。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableContext") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌码或场景标识(扫码点餐)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId") - .IsUnique(); - - b.ToTable("shopping_carts", null, t => - { - t.HasComment("用户购物车,按租户/门店隔离。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.Order", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("取消原因。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("下单渠道。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("顾客姓名。"); - - b.Property("CustomerPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("顾客手机号。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryType") - .HasColumnType("integer") - .HasComment("履约类型。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("优惠金额。"); - - b.Property("FinishedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("ItemsAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("商品总额。"); - - b.Property("OrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("订单号。"); - - b.Property("PaidAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付时间。"); - - b.Property("PayableAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额。"); - - b.Property("PaymentStatus") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("QueueNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队号(如有)。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationId") - .HasColumnType("bigint") - .HasComment("预约 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TableNo") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("就餐桌号。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "Status"); - - b.ToTable("orders", null, t => - { - t.HasComment("交易订单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("自定义属性 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("折扣金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品 ID。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("SkuName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("SKU/规格描述。"); - - b.Property("SubTotal") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("小计。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("单位。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("OrderId"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("order_items", null, t => - { - t.HasComment("订单明细。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderStatusHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注信息。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识(可为空表示系统)。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("变更后的状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId", "OccurredAt"); - - b.ToTable("order_status_histories", null, t => - { - t.HasComment("订单状态流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.RefundRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("申请金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("ProcessedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核完成时间。"); - - b.Property("Reason") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("申请原因。"); - - b.Property("RefundNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("退款单号。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("用户提交时间。"); - - b.Property("ReviewNotes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "RefundNo") - .IsUnique(); - - b.ToTable("refund_requests", null, t => - { - t.HasComment("售后/退款申请。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("支付金额。"); - - b.Property("ChannelTransactionId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方渠道单号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Method") - .HasColumnType("integer") - .HasComment("支付方式。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付完成时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始回调内容。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("错误/备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TradeNo") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("平台交易号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("payment_records", null, t => - { - t.HasComment("支付流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRefundRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("退款金额。"); - - b.Property("ChannelRefundId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("渠道退款流水号。"); - - b.Property("CompletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("渠道返回的原始数据 JSON。"); - - b.Property("PaymentRecordId") - .HasColumnType("bigint") - .HasComment("原支付记录标识。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("退款请求时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PaymentRecordId"); - - b.ToTable("payment_refund_records", null, t => - { - t.HasComment("支付渠道退款流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.Product", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CategoryId") - .HasColumnType("bigint") - .HasComment("所属分类。"); - - b.Property("CoverImage") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("主图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("商品描述。"); - - b.Property("EnableDelivery") - .HasColumnType("boolean") - .HasComment("支持配送。"); - - b.Property("EnableDineIn") - .HasColumnType("boolean") - .HasComment("支持堂食。"); - - b.Property("EnablePickup") - .HasColumnType("boolean") - .HasComment("支持自提。"); - - b.Property("GalleryImages") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Gallery 图片逗号分隔。"); - - b.Property("IsFeatured") - .HasColumnType("boolean") - .HasComment("是否热门推荐。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("最大每单限购。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("现价。"); - - b.Property("SpuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("商品编码。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("商品状态。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("库存数量(可选)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("Subtitle") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("副标题/卖点。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("售卖单位(份/杯等)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SpuCode") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("products", null, t => - { - t.HasComment("商品(SPU)信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("MaxSelect") - .HasColumnType("integer") - .HasComment("最大选择数量。"); - - b.Property("MinSelect") - .HasColumnType("integer") - .HasComment("最小选择数量。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "Name"); - - b.ToTable("product_addon_groups", null, t => - { - t.HasComment("加料/做法分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AddonGroupId") - .HasColumnType("bigint") - .HasComment("所属加料分组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选项。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("product_addon_options", null, t => - { - t.HasComment("加料选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称,例如“辣度”“份量”。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型(单选/多选)。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("显示排序。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店,可为空表示所有门店共享。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("product_attribute_groups", null, t => - { - t.HasComment("商品规格/属性分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributeGroupId") - .HasColumnType("bigint") - .HasComment("所属规格组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选中。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AttributeGroupId", "Name") - .IsUnique(); - - b.ToTable("product_attribute_options", null, t => - { - t.HasComment("商品规格选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("分类描述。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分类名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("product_categories", null, t => - { - t.HasComment("商品分类。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductMediaAsset", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Caption") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述或标题。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MediaType") - .HasColumnType("integer") - .HasComment("媒体类型。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品标识。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Url") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("媒资链接。"); - - b.HasKey("Id"); - - b.ToTable("product_media_assets", null, t => - { - t.HasComment("商品媒资素材。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductPricingRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("条件描述(JSON),如会员等级、渠道等。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效结束时间。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("特殊价格。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("RuleType") - .HasColumnType("integer") - .HasComment("策略类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StartTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效开始时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("WeekdaysJson") - .HasColumnType("text") - .HasComment("生效星期(JSON 数组)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "RuleType"); - - b.ToTable("product_pricing_rules", null, t => - { - t.HasComment("商品价格策略,支持会员价/时段价等。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductSku", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("规格属性 JSON(记录选项 ID)。"); - - b.Property("Barcode") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("条形码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("售价。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SkuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("SKU 编码。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("可售库存。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weight") - .HasPrecision(10, 3) - .HasColumnType("numeric(10,3)") - .HasComment("重量(千克)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SkuCode") - .IsUnique(); - - b.ToTable("product_skus", null, t => - { - t.HasComment("商品 SKU,记录具体规格组合价格。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Queues.Entities.QueueTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CalledAt") - .HasColumnType("timestamp with time zone") - .HasComment("叫号时间。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedWaitMinutes") - .HasColumnType("integer") - .HasComment("预计等待分钟。"); - - b.Property("ExpiredAt") - .HasColumnType("timestamp with time zone") - .HasComment("过号时间。"); - - b.Property("PartySize") - .HasColumnType("integer") - .HasComment("就餐人数。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("获取或设置所属门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNumber") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.HasIndex("TenantId", "StoreId", "TicketNumber") - .IsUnique(); - - b.ToTable("queue_tickets", null, t => - { - t.HasComment("排队叫号。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Reservations.Entities.Reservation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CheckInCode") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("核销码/到店码。"); - - b.Property("CheckedInAt") - .HasColumnType("timestamp with time zone") - .HasComment("实际签到时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("客户姓名。"); - - b.Property("CustomerPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PeopleCount") - .HasColumnType("integer") - .HasComment("用餐人数。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("预约号。"); - - b.Property("ReservationTime") - .HasColumnType("timestamp with time zone") - .HasComment("预约时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TablePreference") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌型/标签。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ReservationNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("reservations", null, t => - { - t.HasComment("预约/预订记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.Store", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("Announcement") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("门店公告。"); - - b.Property("BusinessHours") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("门店营业时段描述(备用字符串)。"); - - b.Property("BusinessLicenseImageUrl") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("门店营业执照图片地址(主体不一致模式使用)。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(50) - .HasColumnType("character varying(50)") - .HasComment("门店营业执照号(主体不一致模式使用)。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("门店编码,便于扫码及外部对接。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家或地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("门店海报。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryRadiusKm") - .HasPrecision(6, 2) - .HasColumnType("numeric(6,2)") - .HasComment("默认配送半径(公里)。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("门店描述或公告。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区县信息。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("LegalRepresentative") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasComment("门店法人(主体不一致模式使用)。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("高德/腾讯地图经度。"); - - b.Property("ManagerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("门店负责人姓名。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("门店名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("RegisteredAddress") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("门店注册地址(主体不一致模式使用)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("门店当前运营状态。"); - - b.Property("SupportsDelivery") - .HasColumnType("boolean") - .HasComment("是否支持配送。"); - - b.Property("SupportsDineIn") - .HasColumnType("boolean") - .HasComment("是否支持堂食。"); - - b.Property("SupportsPickup") - .HasColumnType("boolean") - .HasComment("是否支持自提。"); - - b.Property("SupportsQueueing") - .HasColumnType("boolean") - .HasComment("支持排队叫号。"); - - b.Property("SupportsReservation") - .HasColumnType("boolean") - .HasComment("支持预约。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("门店标签(逗号分隔)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("MerchantId", "BusinessLicenseNumber") - .IsUnique() - .HasFilter("\"BusinessLicenseNumber\" IS NOT NULL AND \"Status\" <> 3"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.HasIndex("TenantId", "MerchantId"); - - b.ToTable("stores", null, t => - { - t.HasComment("门店信息,承载营业配置与能力。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreBusinessHour", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CapacityLimit") - .HasColumnType("integer") - .HasComment("最大接待容量或单量限制。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DayOfWeek") - .HasColumnType("integer") - .HasComment("星期几,0 表示周日。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间(本地时间)。"); - - b.Property("HourType") - .HasColumnType("integer") - .HasComment("时段类型(正常营业、休息、预约等)。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间(本地时间)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "DayOfWeek"); - - b.ToTable("store_business_hours", null, t => - { - t.HasComment("门店营业时段配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreDeliveryZone", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("EstimatedMinutes") - .HasColumnType("integer") - .HasComment("预计送达分钟。"); - - b.Property("MinimumOrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("起送价。"); - - b.Property("PolygonGeoJson") - .IsRequired() - .HasColumnType("text") - .HasComment("GeoJSON 表示的多边形范围。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ZoneName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ZoneName"); - - b.ToTable("store_delivery_zones", null, t => - { - t.HasComment("门店配送范围配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreEmployeeShift", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("排班角色。"); - - b.Property("ShiftDate") - .HasColumnType("timestamp with time zone") - .HasComment("班次日期。"); - - b.Property("StaffId") - .HasColumnType("bigint") - .HasComment("员工标识。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ShiftDate", "StaffId") - .IsUnique(); - - b.ToTable("store_employee_shifts", null, t => - { - t.HasComment("门店员工排班记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreHoliday", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Date") - .HasColumnType("timestamp with time zone") - .HasComment("日期。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsClosed") - .HasColumnType("boolean") - .HasComment("是否全天闭店。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("说明内容。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Date") - .IsUnique(); - - b.ToTable("store_holidays", null, t => - { - t.HasComment("门店休息日或特殊营业日。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSetting", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowDaysAhead") - .HasColumnType("integer") - .HasComment("可预约天数(含当天)。"); - - b.Property("AllowToday") - .HasColumnType("boolean") - .HasComment("是否允许当天自提。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultCutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("默认截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单笔自提最大份数。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId") - .IsUnique(); - - b.ToTable("store_pickup_settings", null, t => - { - t.HasComment("门店自提配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSlot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("容量(份数)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("当天结束时间(UTC)。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("档期名称。"); - - b.Property("ReservedCount") - .HasColumnType("integer") - .HasComment("已占用数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("当天开始时间(UTC)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weekdays") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("适用星期(逗号分隔 1-7)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("store_pickup_slots", null, t => - { - t.HasComment("门店自提档期。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTable", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AreaId") - .HasColumnType("bigint") - .HasComment("所在区域 ID。"); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("可容纳人数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("QrCodeUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("桌码二维码地址。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前桌台状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("桌码。"); - - b.Property("Tags") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("桌台标签(堂食、快餐等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "TableCode") - .IsUnique(); - - b.ToTable("store_tables", null, t => - { - t.HasComment("桌台信息与二维码绑定。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTableArea", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("区域描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name") - .IsUnique(); - - b.ToTable("store_table_areas", null, t => - { - t.HasComment("门店桌台区域配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.QuotaPackage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("描述。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否上架。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("配额包名称。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("价格。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型。"); - - b.Property("QuotaValue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配额数值。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("排序。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("QuotaType", "IsActive", "SortOrder"); - - b.ToTable("quota_packages", null, t => - { - t.HasComment("配额包定义(平台提供的可购买配额包)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.Tenant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("text") - .HasComment("详细地址信息。"); - - b.Property("City") - .HasColumnType("text") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("租户短编码,作为跨系统引用的唯一标识。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("主联系人邮箱。"); - - b.Property("ContactName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("主联系人姓名。"); - - b.Property("ContactPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("主联系人电话。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家/地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("品牌海报或封面图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("服务生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("服务到期时间(UTC)。"); - - b.Property("Industry") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所属行业,如餐饮、零售等。"); - - b.Property("LegalEntityName") - .HasColumnType("text") - .HasComment("法人或公司主体名称。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("LOGO 图片地址。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("租户全称或品牌名称。"); - - b.Property("OperatingMode") - .HasColumnType("integer") - .HasComment("经营模式(同一主体/不同主体)。"); - - b.Property("PrimaryOwnerUserId") - .HasColumnType("bigint") - .HasComment("系统内对应的租户所有者账号 ID。"); - - b.Property("Province") - .HasColumnType("text") - .HasComment("所在省份或州。"); - - b.Property("Remarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息,用于运营记录特殊说明。"); - - b.Property("ShortName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("对外展示的简称。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("租户当前状态,涵盖审核、启用、停用等场景。"); - - b.Property("SuspendedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次暂停服务时间。"); - - b.Property("SuspensionReason") - .HasColumnType("text") - .HasComment("暂停或终止的原因说明。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("业务标签集合(逗号分隔)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Website") - .HasColumnType("text") - .HasComment("官网或主要宣传链接。"); - - b.HasKey("Id"); - - b.HasIndex("Code") - .IsUnique(); - - b.HasIndex("ContactPhone") - .IsUnique(); - - b.ToTable("tenants", null, t => - { - t.HasComment("平台租户信息,描述租户的生命周期与基础资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementType") - .HasColumnType("integer") - .HasComment("公告类型。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("公告正文(可为 Markdown/HTML,前端自行渲染)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("失效时间(UTC),为空表示长期有效。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否启用(已弃用,迁移期保留)。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("展示优先级,数值越大越靠前。"); - - b.Property("PublishedAt") - .HasColumnType("timestamp with time zone") - .HasComment("实际发布时间(UTC)。"); - - b.Property("PublisherScope") - .HasColumnType("integer") - .HasComment("发布者范围。"); - - b.Property("PublisherUserId") - .HasColumnType("bigint") - .HasComment("发布者用户 ID(平台或租户后台账号)。"); - - b.Property("RevokedAt") - .HasColumnType("timestamp with time zone") - .HasComment("撤销时间(UTC)。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("ScheduledPublishAt") - .HasColumnType("timestamp with time zone") - .HasComment("预定发布时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("公告状态。"); - - b.Property("TargetParameters") - .HasColumnType("text") - .HasComment("目标受众参数(JSON)。"); - - b.Property("TargetType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("目标受众类型。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("公告标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("Status", "EffectiveFrom") - .HasFilter("\"TenantId\" = 0"); - - b.HasIndex("TenantId", "AnnouncementType", "IsActive"); - - b.HasIndex("TenantId", "EffectiveFrom", "EffectiveTo"); - - b.HasIndex("TenantId", "Status", "EffectiveFrom"); - - b.ToTable("tenant_announcements", null, t => - { - t.HasComment("租户公告。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncementRead", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementId") - .HasColumnType("bigint") - .HasComment("公告 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("已读时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("已读用户 ID(后台账号),为空表示租户级已读。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AnnouncementId", "UserId") - .IsUnique(); - - b.ToTable("tenant_announcement_reads", null, t => - { - t.HasComment("租户公告已读记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantBillingStatement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AmountDue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额(原始金额)。"); - - b.Property("AmountPaid") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("BillingType") - .HasColumnType("integer") - .HasComment("账单类型(订阅账单/配额包账单/手动账单/续费账单)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Currency") - .IsRequired() - .ValueGeneratedOnAdd() - .HasMaxLength(8) - .HasColumnType("character varying(8)") - .HasDefaultValue("CNY") - .HasComment("货币类型(默认 CNY)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("折扣金额。"); - - b.Property("DueDate") - .HasColumnType("timestamp with time zone") - .HasComment("到期日。"); - - b.Property("LineItemsJson") - .HasColumnType("text") - .HasComment("账单明细 JSON,记录各项费用。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息(如:人工备注、取消原因等)。"); - - b.Property("OverdueNotifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("逾期通知时间。"); - - b.Property("PeriodEnd") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期结束时间。"); - - b.Property("PeriodStart") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期开始时间。"); - - b.Property("ReminderSentAt") - .HasColumnType("timestamp with time zone") - .HasComment("提醒发送时间(续费提醒、逾期提醒等)。"); - - b.Property("StatementNo") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("账单编号,供对账查询。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前付款状态。"); - - b.Property("SubscriptionId") - .HasColumnType("bigint") - .HasComment("关联的订阅 ID(仅当 BillingType 为 Subscription 或 Renewal 时有值)。"); - - b.Property("TaxAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("税费金额。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("CreatedAt") - .HasDatabaseName("idx_billing_created_at"); - - b.HasIndex("Status", "DueDate") - .HasDatabaseName("idx_billing_status_duedate") - .HasFilter("\"Status\" IN (0, 2)"); - - b.HasIndex("TenantId", "StatementNo") - .IsUnique(); - - b.HasIndex("TenantId", "Status", "DueDate") - .HasDatabaseName("idx_billing_tenant_status_duedate"); - - b.ToTable("tenant_billing_statements", null, t => - { - t.HasComment("租户账单,用于呈现周期性收费。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantNotification", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("发布通道(站内、邮件、短信等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("通知正文。"); - - b.Property("MetadataJson") - .HasColumnType("text") - .HasComment("附加元数据 JSON。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("租户是否已阅读。"); - - b.Property("SentAt") - .HasColumnType("timestamp with time zone") - .HasComment("推送时间。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("通知重要级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("通知标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Channel", "SentAt"); - - b.ToTable("tenant_notifications", null, t => - { - t.HasComment("面向租户的站内通知或消息推送。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantPackage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("套餐描述,包含适用场景、权益等。"); - - b.Property("FeaturePoliciesJson") - .HasColumnType("text") - .HasComment("权益明细 JSON,记录自定义特性开关。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否仍启用(平台控制)。"); - - b.Property("IsAllowNewTenantPurchase") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否允许新租户购买/选择(仅影响新购)。"); - - b.Property("IsPublicVisible") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否对外可见(展示页/套餐列表可见性)。"); - - b.Property("IsRecommended") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false) - .HasComment("是否推荐展示(运营推荐标识)。"); - - b.Property("MaxAccountCount") - .HasColumnType("integer") - .HasComment("允许创建的最大账号数。"); - - b.Property("MaxDeliveryOrders") - .HasColumnType("integer") - .HasComment("每月可调用的配送单数量上限。"); - - b.Property("MaxSmsCredits") - .HasColumnType("integer") - .HasComment("每月短信额度上限。"); - - b.Property("MaxStorageGb") - .HasColumnType("integer") - .HasComment("存储容量上限(GB)。"); - - b.Property("MaxStoreCount") - .HasColumnType("integer") - .HasComment("允许的最大门店数。"); - - b.Property("MonthlyPrice") - .HasColumnType("numeric") - .HasComment("月付价格,单位:人民币元。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("套餐名称,展示给租户的简称。"); - - b.Property("PackageType") - .HasColumnType("integer") - .HasComment("套餐分类(试用、标准、旗舰等)。"); - - b.Property("PublishStatus") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("发布状态:0=草稿,1=已发布。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("展示排序,数值越小越靠前。"); - - b.PrimitiveCollection("Tags") - .IsRequired() - .HasColumnType("text[]") - .HasComment("套餐标签(用于展示与对比页)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("YearlyPrice") - .HasColumnType("numeric") - .HasComment("年付价格,单位:人民币元。"); - - b.HasKey("Id"); - - b.HasIndex("IsActive", "SortOrder"); - - b.HasIndex("PublishStatus", "IsActive", "IsPublicVisible", "IsAllowNewTenantPurchase", "SortOrder"); - - b.ToTable("tenant_packages", null, t => - { - t.HasComment("平台提供的租户套餐定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantPayment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("支付金额。"); - - b.Property("BillingStatementId") - .HasColumnType("bigint") - .HasComment("关联的账单 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Method") - .HasColumnType("integer") - .HasComment("支付方式。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付时间。"); - - b.Property("ProofUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("支付凭证 URL。"); - - b.Property("RefundReason") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("退款原因。"); - - b.Property("RefundedAt") - .HasColumnType("timestamp with time zone") - .HasComment("退款时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TransactionNo") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("交易号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("VerifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核时间。"); - - b.Property("VerifiedBy") - .HasColumnType("bigint") - .HasComment("审核人 ID(管理员)。"); - - b.HasKey("Id"); - - b.HasIndex("TransactionNo") - .HasDatabaseName("idx_payment_transaction_no") - .HasFilter("\"TransactionNo\" IS NOT NULL"); - - b.HasIndex("BillingStatementId", "PaidAt") - .HasDatabaseName("idx_payment_billing_paidat"); - - b.HasIndex("TenantId", "BillingStatementId"); - - b.ToTable("tenant_payments", null, t => - { - t.HasComment("租户支付记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaPackagePurchase", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiredAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(可选)。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("购买价格。"); - - b.Property("PurchasedAt") - .HasColumnType("timestamp with time zone") - .HasComment("购买时间。"); - - b.Property("QuotaPackageId") - .HasColumnType("bigint") - .HasComment("配额包 ID。"); - - b.Property("QuotaValue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("购买时的配额值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "QuotaPackageId", "PurchasedAt"); - - b.ToTable("tenant_quota_package_purchases", null, t => - { - t.HasComment("租户配额包购买记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaUsage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LastResetAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次重置时间。"); - - b.Property("LimitValue") - .HasColumnType("numeric") - .HasComment("当前配额上限。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型,例如门店数、短信条数等。"); - - b.Property("ResetCycle") - .HasColumnType("text") - .HasComment("配额刷新周期描述(如月、年)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedValue") - .HasColumnType("numeric") - .HasComment("已消耗的数量。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "QuotaType") - .IsUnique(); - - b.ToTable("tenant_quota_usages", null, t => - { - t.HasComment("租户配额使用情况快照。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaUsageHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChangeAmount") - .HasColumnType("numeric") - .HasComment("变更量(可选)。"); - - b.Property("ChangeReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("变更原因(可选)。"); - - b.Property("ChangeType") - .HasColumnType("integer") - .HasComment("变更类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LimitValue") - .HasColumnType("numeric") - .HasComment("限额值(记录时刻的快照)。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型。"); - - b.Property("RecordedAt") - .HasColumnType("timestamp with time zone") - .HasComment("记录时间(UTC)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedValue") - .HasColumnType("numeric") - .HasComment("已使用值(记录时刻的快照)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "RecordedAt"); - - b.HasIndex("TenantId", "QuotaType", "RecordedAt"); - - b.ToTable("tenant_quota_usage_histories", null, t => - { - t.HasComment("租户配额使用历史记录(用于追踪配额上下限与使用量的时间序列变化)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantReviewClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ClaimedAt") - .HasColumnType("timestamp with time zone") - .HasComment("领取时间(UTC)。"); - - b.Property("ClaimedBy") - .HasColumnType("bigint") - .HasComment("领取人用户 ID。"); - - b.Property("ClaimedByName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("领取人名称(展示用快照)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReleasedAt") - .HasColumnType("timestamp with time zone") - .HasComment("释放时间(UTC),未释放时为 null。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("被领取的租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("ClaimedBy"); - - b.HasIndex("TenantId") - .IsUnique() - .HasFilter("\"ReleasedAt\" IS NULL AND \"DeletedAt\" IS NULL"); - - b.ToTable("tenant_review_claims", null, t => - { - t.HasComment("租户入驻审核领取记录(防止多管理员并发审核)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscription", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AutoRenew") - .HasColumnType("boolean") - .HasComment("是否开启自动续费。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("订阅生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("订阅到期时间(UTC)。"); - - b.Property("NextBillingDate") - .HasColumnType("timestamp with time zone") - .HasComment("下一个计费时间,配合自动续费使用。"); - - b.Property("Notes") - .HasColumnType("text") - .HasComment("运营备注信息。"); - - b.Property("ScheduledPackageId") - .HasColumnType("bigint") - .HasComment("若已排期升降配,对应的新套餐 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("订阅当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TenantPackageId") - .HasColumnType("bigint") - .HasComment("当前订阅关联的套餐标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantPackageId"); - - b.ToTable("tenant_subscriptions", null, t => - { - t.HasComment("租户套餐订阅记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscriptionHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasColumnType("numeric") - .HasComment("相关费用。"); - - b.Property("ChangeType") - .HasColumnType("integer") - .HasComment("变更类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Currency") - .HasMaxLength(8) - .HasColumnType("character varying(8)") - .HasComment("币种。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("FromPackageId") - .HasColumnType("bigint") - .HasComment("原套餐 ID。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("租户标识。"); - - b.Property("TenantSubscriptionId") - .HasColumnType("bigint") - .HasComment("对应的订阅 ID。"); - - b.Property("ToPackageId") - .HasColumnType("bigint") - .HasComment("新套餐 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantSubscriptionId"); - - b.ToTable("tenant_subscription_histories", null, t => - { - t.HasComment("租户套餐订阅变更记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantVerificationProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdditionalDataJson") - .HasColumnType("text") - .HasComment("附加资料(JSON)。"); - - b.Property("BankAccountName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("开户名。"); - - b.Property("BankAccountNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("银行账号。"); - - b.Property("BankName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("银行名称。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照编号。"); - - b.Property("BusinessLicenseUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营业执照文件地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LegalPersonIdBackUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证反面。"); - - b.Property("LegalPersonIdFrontUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证正面。"); - - b.Property("LegalPersonIdNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("法人身份证号。"); - - b.Property("LegalPersonName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人姓名。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注。"); - - b.Property("ReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核时间。"); - - b.Property("ReviewedBy") - .HasColumnType("bigint") - .HasComment("审核人 ID。"); - - b.Property("ReviewedByName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("审核人姓名。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("实名状态。"); - - b.Property("SubmittedAt") - .HasColumnType("timestamp with time zone") - .HasComment("提交时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("对应的租户标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId") - .IsUnique(); - - b.ToTable("tenant_verification_profiles", null, t => - { - t.HasComment("租户实名认证资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.HasOne("TakeoutSaaS.Domain.Orders.Entities.Order", null) - .WithMany() - .HasForeignKey("OrderId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251229071911_AddMerchantManagement.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251229071911_AddMerchantManagement.cs deleted file mode 100644 index dcf8f5b..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251229071911_AddMerchantManagement.cs +++ /dev/null @@ -1,244 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - /// - public partial class AddMerchantManagement : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "OperatingMode", - table: "tenants", - type: "integer", - nullable: true, - comment: "经营模式(同一主体/不同主体)。"); - - migrationBuilder.AddColumn( - name: "BusinessLicenseImageUrl", - table: "stores", - type: "character varying(500)", - maxLength: 500, - nullable: true, - comment: "门店营业执照图片地址(主体不一致模式使用)。"); - - migrationBuilder.AddColumn( - name: "BusinessLicenseNumber", - table: "stores", - type: "character varying(50)", - maxLength: 50, - nullable: true, - comment: "门店营业执照号(主体不一致模式使用)。"); - - migrationBuilder.AddColumn( - name: "LegalRepresentative", - table: "stores", - type: "character varying(100)", - maxLength: 100, - nullable: true, - comment: "门店法人(主体不一致模式使用)。"); - - migrationBuilder.AddColumn( - name: "RegisteredAddress", - table: "stores", - type: "character varying(500)", - maxLength: 500, - nullable: true, - comment: "门店注册地址(主体不一致模式使用)。"); - - migrationBuilder.AddColumn( - name: "ApprovedAt", - table: "merchants", - type: "timestamp with time zone", - nullable: true, - comment: "审核通过时间。"); - - migrationBuilder.AddColumn( - name: "ApprovedBy", - table: "merchants", - type: "bigint", - nullable: true, - comment: "审核通过人。"); - - migrationBuilder.AddColumn( - name: "ClaimExpiresAt", - table: "merchants", - type: "timestamp with time zone", - nullable: true, - comment: "领取过期时间。"); - - migrationBuilder.AddColumn( - name: "ClaimedAt", - table: "merchants", - type: "timestamp with time zone", - nullable: true, - comment: "领取时间。"); - - migrationBuilder.AddColumn( - name: "ClaimedBy", - table: "merchants", - type: "bigint", - nullable: true, - comment: "当前领取人。"); - - migrationBuilder.AddColumn( - name: "ClaimedByName", - table: "merchants", - type: "character varying(100)", - maxLength: 100, - nullable: true, - comment: "当前领取人姓名。"); - - migrationBuilder.AddColumn( - name: "FrozenAt", - table: "merchants", - type: "timestamp with time zone", - nullable: true, - comment: "冻结时间。"); - - migrationBuilder.AddColumn( - name: "FrozenReason", - table: "merchants", - type: "character varying(500)", - maxLength: 500, - nullable: true, - comment: "冻结原因。"); - - migrationBuilder.AddColumn( - name: "IsFrozen", - table: "merchants", - type: "boolean", - nullable: false, - defaultValue: false, - comment: "是否冻结业务。"); - - migrationBuilder.AddColumn( - name: "LastReviewedBy", - table: "merchants", - type: "bigint", - nullable: true, - comment: "最近一次审核人。"); - - migrationBuilder.AddColumn( - name: "OperatingMode", - table: "merchants", - type: "integer", - nullable: true, - comment: "经营模式(同一主体/不同主体)。"); - - migrationBuilder.AddColumn( - name: "RowVersion", - table: "merchants", - type: "bytea", - rowVersion: true, - nullable: false, - defaultValue: new byte[0], - comment: "并发控制版本。"); - - migrationBuilder.CreateIndex( - name: "IX_stores_MerchantId_BusinessLicenseNumber", - table: "stores", - columns: new[] { "MerchantId", "BusinessLicenseNumber" }, - unique: true, - filter: "\"BusinessLicenseNumber\" IS NOT NULL AND \"Status\" <> 3"); - - migrationBuilder.CreateIndex( - name: "IX_merchants_ClaimedBy", - table: "merchants", - column: "ClaimedBy"); - - migrationBuilder.CreateIndex( - name: "IX_merchants_TenantId_Status", - table: "merchants", - columns: new[] { "TenantId", "Status" }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_stores_MerchantId_BusinessLicenseNumber", - table: "stores"); - - migrationBuilder.DropIndex( - name: "IX_merchants_ClaimedBy", - table: "merchants"); - - migrationBuilder.DropIndex( - name: "IX_merchants_TenantId_Status", - table: "merchants"); - - migrationBuilder.DropColumn( - name: "OperatingMode", - table: "tenants"); - - migrationBuilder.DropColumn( - name: "BusinessLicenseImageUrl", - table: "stores"); - - migrationBuilder.DropColumn( - name: "BusinessLicenseNumber", - table: "stores"); - - migrationBuilder.DropColumn( - name: "LegalRepresentative", - table: "stores"); - - migrationBuilder.DropColumn( - name: "RegisteredAddress", - table: "stores"); - - migrationBuilder.DropColumn( - name: "ApprovedAt", - table: "merchants"); - - migrationBuilder.DropColumn( - name: "ApprovedBy", - table: "merchants"); - - migrationBuilder.DropColumn( - name: "ClaimExpiresAt", - table: "merchants"); - - migrationBuilder.DropColumn( - name: "ClaimedAt", - table: "merchants"); - - migrationBuilder.DropColumn( - name: "ClaimedBy", - table: "merchants"); - - migrationBuilder.DropColumn( - name: "ClaimedByName", - table: "merchants"); - - migrationBuilder.DropColumn( - name: "FrozenAt", - table: "merchants"); - - migrationBuilder.DropColumn( - name: "FrozenReason", - table: "merchants"); - - migrationBuilder.DropColumn( - name: "IsFrozen", - table: "merchants"); - - migrationBuilder.DropColumn( - name: "LastReviewedBy", - table: "merchants"); - - migrationBuilder.DropColumn( - name: "OperatingMode", - table: "merchants"); - - migrationBuilder.DropColumn( - name: "RowVersion", - table: "merchants"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251231124137_AddStoreManagementEntities.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251231124137_AddStoreManagementEntities.Designer.cs deleted file mode 100644 index bac5d9d..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251231124137_AddStoreManagementEntities.Designer.cs +++ /dev/null @@ -1,7391 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.App.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - [DbContext(typeof(TakeoutAppDbContext))] - [Migration("20251231124137_AddStoreManagementEntities")] - partial class AddStoreManagementEntities - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.1") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricAlertRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionJson") - .IsRequired() - .HasColumnType("text") - .HasComment("触发条件 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Enabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("关联指标。"); - - b.Property("NotificationChannels") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("通知渠道。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("告警级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "Severity"); - - b.ToTable("metric_alert_rules", null, t => - { - t.HasComment("指标告警规则。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricDefinition", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("指标编码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultAggregation") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("默认聚合方式。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("说明。"); - - b.Property("DimensionsJson") - .HasColumnType("text") - .HasComment("维度描述 JSON。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("指标名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("metric_definitions", null, t => - { - t.HasComment("指标定义,描述可观测的数据点。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricSnapshot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DimensionKey") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("维度键(JSON)。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("指标定义 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Value") - .HasPrecision(18, 4) - .HasColumnType("numeric(18,4)") - .HasComment("数值。"); - - b.Property("WindowEnd") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口结束。"); - - b.Property("WindowStart") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口开始。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "DimensionKey", "WindowStart", "WindowEnd") - .IsUnique(); - - b.ToTable("metric_snapshots", null, t => - { - t.HasComment("指标快照,用于大盘展示。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.Coupon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("券码或序列号。"); - - b.Property("CouponTemplateId") - .HasColumnType("bigint") - .HasComment("模板标识。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("发放时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID(已使用时记录)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedAt") - .HasColumnType("timestamp with time zone") - .HasComment("使用时间。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("归属用户。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("coupons", null, t => - { - t.HasComment("用户领取的券。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.CouponTemplate", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowStack") - .HasColumnType("boolean") - .HasComment("是否允许叠加其他优惠。"); - - b.Property("ChannelsJson") - .HasColumnType("text") - .HasComment("发放渠道(JSON)。"); - - b.Property("ClaimedQuantity") - .HasColumnType("integer") - .HasComment("已领取数量。"); - - b.Property("CouponType") - .HasColumnType("integer") - .HasComment("券类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("DiscountCap") - .HasColumnType("numeric") - .HasComment("折扣上限(针对折扣券)。"); - - b.Property("MinimumSpend") - .HasColumnType("numeric") - .HasComment("最低消费门槛。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("模板名称。"); - - b.Property("ProductScopeJson") - .HasColumnType("text") - .HasComment("适用品类或商品范围(JSON)。"); - - b.Property("RelativeValidDays") - .HasColumnType("integer") - .HasComment("有效天数(相对发放时间)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreScopeJson") - .HasColumnType("text") - .HasComment("适用门店 ID 集合(JSON)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TotalQuantity") - .HasColumnType("integer") - .HasComment("总发放数量上限。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ValidFrom") - .HasColumnType("timestamp with time zone") - .HasComment("可用开始时间。"); - - b.Property("ValidTo") - .HasColumnType("timestamp with time zone") - .HasComment("可用结束时间。"); - - b.Property("Value") - .HasColumnType("numeric") - .HasComment("面值或折扣额度。"); - - b.HasKey("Id"); - - b.ToTable("coupon_templates", null, t => - { - t.HasComment("优惠券模板。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.PromotionCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AudienceDescription") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("目标人群描述。"); - - b.Property("BannerUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营销素材(如 banner)。"); - - b.Property("Budget") - .HasColumnType("numeric") - .HasComment("预算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("PromotionType") - .HasColumnType("integer") - .HasComment("活动类型。"); - - b.Property("RulesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("活动规则 JSON。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("活动状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("promotion_campaigns", null, t => - { - t.HasComment("营销活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChatSessionId") - .HasColumnType("bigint") - .HasComment("会话标识。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("消息内容。"); - - b.Property("ContentType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("消息类型(文字/图片/语音等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRead") - .HasColumnType("boolean") - .HasComment("是否已读。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("读取时间。"); - - b.Property("SenderType") - .HasColumnType("integer") - .HasComment("发送方类型。"); - - b.Property("SenderUserId") - .HasColumnType("bigint") - .HasComment("发送方用户 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ChatSessionId", "CreatedAt"); - - b.ToTable("chat_messages", null, t => - { - t.HasComment("会话消息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AgentUserId") - .HasColumnType("bigint") - .HasComment("当前客服员工 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("顾客用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndedAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("IsBotActive") - .HasColumnType("boolean") - .HasComment("是否机器人接待中。"); - - b.Property("SessionCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话编号。"); - - b.Property("StartedAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店(可空为平台)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionCode") - .IsUnique(); - - b.ToTable("chat_sessions", null, t => - { - t.HasComment("客服会话。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.SupportTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AssignedAgentId") - .HasColumnType("bigint") - .HasComment("指派的客服。"); - - b.Property("ClosedAt") - .HasColumnType("timestamp with time zone") - .HasComment("关闭时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("客户用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .IsRequired() - .HasColumnType("text") - .HasComment("工单详情。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单(如有)。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("优先级。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("Subject") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("工单主题。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("工单编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TicketNo") - .IsUnique(); - - b.ToTable("support_tickets", null, t => - { - t.HasComment("客服工单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.TicketComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttachmentsJson") - .HasColumnType("text") - .HasComment("附件 JSON。"); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人 ID。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsInternal") - .HasColumnType("boolean") - .HasComment("是否内部备注。"); - - b.Property("SupportTicketId") - .HasColumnType("bigint") - .HasComment("工单标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SupportTicketId"); - - b.ToTable("ticket_comments", null, t => - { - t.HasComment("工单评论/流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryEvent", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryOrderId") - .HasColumnType("bigint") - .HasComment("配送单标识。"); - - b.Property("EventType") - .HasColumnType("integer") - .HasComment("事件类型。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("事件描述。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始数据 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DeliveryOrderId", "EventType"); - - b.ToTable("delivery_events", null, t => - { - t.HasComment("配送状态事件流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CourierName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("骑手姓名。"); - - b.Property("CourierPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("骑手电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveredAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("DispatchedAt") - .HasColumnType("timestamp with time zone") - .HasComment("下发时间。"); - - b.Property("FailureReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("异常原因。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("获取或设置关联订单 ID。"); - - b.Property("PickedUpAt") - .HasColumnType("timestamp with time zone") - .HasComment("取餐时间。"); - - b.Property("Provider") - .HasColumnType("integer") - .HasComment("配送服务商。"); - - b.Property("ProviderOrderId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方配送单号。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId") - .IsUnique(); - - b.ToTable("delivery_orders", null, t => - { - t.HasComment("配送单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliateOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("推广人标识。"); - - b.Property("BuyerUserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedCommission") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("预计佣金。"); - - b.Property("OrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("订单金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("SettledAt") - .HasColumnType("timestamp with time zone") - .HasComment("结算完成时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "OrderId") - .IsUnique(); - - b.ToTable("affiliate_orders", null, t => - { - t.HasComment("分销订单记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePartner", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChannelType") - .HasColumnType("integer") - .HasComment("渠道类型。"); - - b.Property("CommissionRate") - .HasColumnType("numeric") - .HasComment("分成比例(0-1)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称或渠道名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID(如绑定平台账号)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DisplayName"); - - b.ToTable("affiliate_partners", null, t => - { - t.HasComment("分销/推广合作伙伴。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePayout", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("合作伙伴标识。"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("结算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("打款时间。"); - - b.Property("Period") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("结算周期描述。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "Period") - .IsUnique(); - - b.ToTable("affiliate_payouts", null, t => - { - t.HasComment("佣金结算记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowMakeupCount") - .HasColumnType("integer") - .HasComment("支持补签次数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("活动描述。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("结束日期。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("RewardsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("连签奖励 JSON。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("开始日期。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name"); - - b.ToTable("checkin_campaigns", null, t => - { - t.HasComment("签到活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CheckInCampaignId") - .HasColumnType("bigint") - .HasComment("活动标识。"); - - b.Property("CheckInDate") - .HasColumnType("timestamp with time zone") - .HasComment("签到日期(本地)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsMakeup") - .HasColumnType("boolean") - .HasComment("是否补签。"); - - b.Property("RewardJson") - .IsRequired() - .HasColumnType("text") - .HasComment("获得奖励 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "CheckInCampaignId", "UserId", "CheckInDate") - .IsUnique(); - - b.ToTable("checkin_records", null, t => - { - t.HasComment("用户签到记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsDeleted") - .HasColumnType("boolean") - .HasComment("状态。"); - - b.Property("ParentId") - .HasColumnType("bigint") - .HasComment("父级评论 ID。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "CreatedAt"); - - b.ToTable("community_comments", null, t => - { - t.HasComment("社区评论。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityPost", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("作者用户 ID。"); - - b.Property("CommentCount") - .HasColumnType("integer") - .HasComment("评论数。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LikeCount") - .HasColumnType("integer") - .HasComment("点赞数。"); - - b.Property("MediaJson") - .HasColumnType("text") - .HasComment("媒体资源 JSON。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AuthorUserId", "CreatedAt"); - - b.ToTable("community_posts", null, t => - { - t.HasComment("社区动态。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityReaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态 ID。"); - - b.Property("ReactedAt") - .HasColumnType("timestamp with time zone") - .HasComment("时间戳。"); - - b.Property("ReactionType") - .HasColumnType("integer") - .HasComment("反应类型。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "UserId") - .IsUnique(); - - b.ToTable("community_reactions", null, t => - { - t.HasComment("社区互动反馈。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentCount") - .HasColumnType("integer") - .HasComment("当前已参与人数。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("GroupOrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("拼单编号。"); - - b.Property("GroupPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("拼团价格。"); - - b.Property("LeaderUserId") - .HasColumnType("bigint") - .HasComment("团长用户 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("关联商品或套餐。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("拼团状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("SucceededAt") - .HasColumnType("timestamp with time zone") - .HasComment("成团时间。"); - - b.Property("TargetCount") - .HasColumnType("integer") - .HasComment("成团需要的人数。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderNo") - .IsUnique(); - - b.ToTable("group_orders", null, t => - { - t.HasComment("拼单活动。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupParticipant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GroupOrderId") - .HasColumnType("bigint") - .HasComment("拼单活动标识。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("参与时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("对应订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("参与状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderId", "UserId") - .IsUnique(); - - b.ToTable("group_participants", null, t => - { - t.HasComment("拼单参与者。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryAdjustment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdjustmentType") - .HasColumnType("integer") - .HasComment("调整类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("InventoryItemId") - .HasColumnType("bigint") - .HasComment("对应的库存记录标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("调整数量,正数增加,负数减少。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("原因说明。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "InventoryItemId", "OccurredAt"); - - b.ToTable("inventory_adjustments", null, t => - { - t.HasComment("库存调整记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryBatch", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("ProductionDate") - .HasColumnType("timestamp with time zone") - .HasComment("生产日期。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("入库数量。"); - - b.Property("RemainingQuantity") - .HasColumnType("integer") - .HasComment("剩余数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber") - .IsUnique(); - - b.ToTable("inventory_batches", null, t => - { - t.HasComment("SKU 批次信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchConsumeStrategy") - .HasColumnType("integer") - .HasComment("批次扣减策略。"); - - b.Property("BatchNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号,可为空表示混批。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售商品。"); - - b.Property("IsSoldOut") - .HasColumnType("boolean") - .HasComment("是否标记售罄。"); - - b.Property("Location") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("储位或仓位信息。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单品限购(覆盖商品级 MaxQuantityPerOrder)。"); - - b.Property("PresaleCapacity") - .HasColumnType("integer") - .HasComment("预售名额(上限)。"); - - b.Property("PresaleEndTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售结束时间(UTC)。"); - - b.Property("PresaleLocked") - .HasColumnType("integer") - .HasComment("当前预售已锁定数量。"); - - b.Property("PresaleStartTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售开始时间(UTC)。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("QuantityOnHand") - .HasColumnType("integer") - .HasComment("可用库存。"); - - b.Property("QuantityReserved") - .HasColumnType("integer") - .HasComment("已锁定库存(订单占用)。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("SafetyStock") - .HasColumnType("integer") - .HasComment("安全库存阈值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber"); - - b.ToTable("inventory_items", null, t => - { - t.HasComment("SKU 在门店的库存信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryLockRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("IdempotencyKey") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("幂等键。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售锁定。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU ID。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("锁定数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("锁定状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "IdempotencyKey") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "Status"); - - b.ToTable("inventory_lock_records", null, t => - { - t.HasComment("库存锁定记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberPointLedger", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BalanceAfterChange") - .HasColumnType("integer") - .HasComment("变动后余额。"); - - b.Property("ChangeAmount") - .HasColumnType("integer") - .HasComment("变动数量,可为负值。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(如适用)。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Reason") - .HasColumnType("integer") - .HasComment("变动原因。"); - - b.Property("SourceId") - .HasColumnType("bigint") - .HasComment("来源 ID(订单、活动等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_point_ledgers", null, t => - { - t.HasComment("积分变动流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AvatarUrl") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像。"); - - b.Property("BirthDate") - .HasColumnType("timestamp with time zone") - .HasComment("生日。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GrowthValue") - .HasColumnType("integer") - .HasComment("成长值/经验值。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("注册时间。"); - - b.Property("MemberTierId") - .HasColumnType("bigint") - .HasComment("当前会员等级 ID。"); - - b.Property("Mobile") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("Nickname") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称。"); - - b.Property("PointsBalance") - .HasColumnType("integer") - .HasComment("会员积分余额。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会员状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Mobile") - .IsUnique(); - - b.ToTable("member_profiles", null, t => - { - t.HasComment("会员档案。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberTier", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BenefitsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("等级权益(JSON)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("等级名称。"); - - b.Property("RequiredGrowth") - .HasColumnType("integer") - .HasComment("所需成长值。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("member_tiers", null, t => - { - t.HasComment("会员等级定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.Merchant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("ApprovedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核通过时间。"); - - b.Property("ApprovedBy") - .HasColumnType("bigint") - .HasComment("审核通过人。"); - - b.Property("BrandAlias") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("品牌简称或别名。"); - - b.Property("BrandName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("品牌名称(对外展示)。"); - - b.Property("BusinessLicenseImageUrl") - .HasColumnType("text") - .HasComment("营业执照扫描件地址。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照号。"); - - b.Property("Category") - .HasColumnType("text") - .HasComment("品牌所属品类,如火锅、咖啡等。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("ClaimExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("领取过期时间。"); - - b.Property("ClaimedAt") - .HasColumnType("timestamp with time zone") - .HasComment("领取时间。"); - - b.Property("ClaimedBy") - .HasColumnType("bigint") - .HasComment("当前领取人。"); - - b.Property("ClaimedByName") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasComment("当前领取人姓名。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("联系邮箱。"); - - b.Property("ContactPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在区县。"); - - b.Property("FrozenAt") - .HasColumnType("timestamp with time zone") - .HasComment("冻结时间。"); - - b.Property("FrozenReason") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("冻结原因。"); - - b.Property("IsFrozen") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false) - .HasComment("是否冻结业务。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("入驻时间。"); - - b.Property("LastReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次审核时间。"); - - b.Property("LastReviewedBy") - .HasColumnType("bigint") - .HasComment("最近一次审核人。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度信息。"); - - b.Property("LegalPerson") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人或负责人姓名。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("品牌 Logo。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度信息。"); - - b.Property("OperatingMode") - .HasColumnType("integer") - .HasComment("经营模式(同一主体/不同主体)。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注或驳回原因。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制版本。"); - - b.Property("ServicePhone") - .HasColumnType("text") - .HasComment("客服电话。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("入驻状态。"); - - b.Property("SupportEmail") - .HasColumnType("text") - .HasComment("客服邮箱。"); - - b.Property("TaxNumber") - .HasColumnType("text") - .HasComment("税号/统一社会信用代码。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("ClaimedBy"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Status"); - - b.ToTable("merchants", null, t => - { - t.HasComment("商户主体信息,承载入驻和资质审核结果。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("显示顺序,越小越靠前。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否可用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("类目名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("merchant_categories", null, t => - { - t.HasComment("商户可选类目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantContract", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ContractNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("合同编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同结束时间。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("合同文件存储地址。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("SignedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签署时间。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("合同状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TerminatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("终止时间。"); - - b.Property("TerminationReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("终止原因。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "ContractNumber") - .IsUnique(); - - b.ToTable("merchant_contracts", null, t => - { - t.HasComment("商户合同记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantDocument", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DocumentNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("证照编号。"); - - b.Property("DocumentType") - .HasColumnType("integer") - .HasComment("证照类型。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期日期。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("证照文件链接。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签发日期。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Remarks") - .HasColumnType("text") - .HasComment("审核备注或驳回原因。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("审核状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "DocumentType"); - - b.ToTable("merchant_documents", null, t => - { - t.HasComment("商户提交的资质或证照材料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantStaff", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Email") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("邮箱地址。"); - - b.Property("IdentityUserId") - .HasColumnType("bigint") - .HasComment("登录账号 ID(指向统一身份体系)。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("员工姓名。"); - - b.Property("PermissionsJson") - .HasColumnType("text") - .HasComment("自定义权限(JSON)。"); - - b.Property("Phone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("员工角色类型。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("员工状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("可选的关联门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "Phone"); - - b.ToTable("merchant_staff", null, t => - { - t.HasComment("商户员工账号,支持门店维度分配。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.MapLocation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Landmark") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("打车/导航落点描述。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("名称。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店 ID,可空表示独立 POI。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("map_locations", null, t => - { - t.HasComment("地图 POI 信息,用于门店定位和推荐。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.NavigationRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("来源通道(小程序、H5 等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("请求时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TargetApp") - .HasColumnType("integer") - .HasComment("跳转的地图应用。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId", "RequestedAt"); - - b.ToTable("navigation_requests", null, t => - { - t.HasComment("用户发起的导航请求日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("扩展 JSON(规格、加料选项等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品或 SKU 标识。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称快照。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("自定义备注(口味要求)。"); - - b.Property("ShoppingCartId") - .HasColumnType("bigint") - .HasComment("所属购物车标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价快照。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ShoppingCartId"); - - b.ToTable("cart_items", null, t => - { - t.HasComment("购物车条目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItemAddon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CartItemId") - .HasColumnType("bigint") - .HasComment("所属购物车条目。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("OptionId") - .HasColumnType("bigint") - .HasComment("选项 ID(可对应 ProductAddonOption)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("cart_item_addons", null, t => - { - t.HasComment("购物车条目的加料/附加项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CheckoutSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("SessionToken") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话 Token。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.Property("ValidationResultJson") - .IsRequired() - .HasColumnType("text") - .HasComment("校验结果明细 JSON。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionToken") - .IsUnique(); - - b.ToTable("checkout_sessions", null, t => - { - t.HasComment("结账会话,记录校验上下文。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.ShoppingCart", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryPreference") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("履约方式(堂食/自提/配送)缓存。"); - - b.Property("LastModifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次修改时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("购物车状态,包含正常/锁定。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableContext") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌码或场景标识(扫码点餐)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId") - .IsUnique(); - - b.ToTable("shopping_carts", null, t => - { - t.HasComment("用户购物车,按租户/门店隔离。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.Order", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("取消原因。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("下单渠道。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("顾客姓名。"); - - b.Property("CustomerPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("顾客手机号。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryType") - .HasColumnType("integer") - .HasComment("履约类型。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("优惠金额。"); - - b.Property("FinishedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("ItemsAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("商品总额。"); - - b.Property("OrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("订单号。"); - - b.Property("PaidAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付时间。"); - - b.Property("PayableAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额。"); - - b.Property("PaymentStatus") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("QueueNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队号(如有)。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationId") - .HasColumnType("bigint") - .HasComment("预约 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TableNo") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("就餐桌号。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "Status"); - - b.ToTable("orders", null, t => - { - t.HasComment("交易订单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("自定义属性 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("折扣金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品 ID。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("SkuName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("SKU/规格描述。"); - - b.Property("SubTotal") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("小计。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("单位。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("OrderId"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("order_items", null, t => - { - t.HasComment("订单明细。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderStatusHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注信息。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识(可为空表示系统)。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("变更后的状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId", "OccurredAt"); - - b.ToTable("order_status_histories", null, t => - { - t.HasComment("订单状态流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.RefundRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("申请金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("ProcessedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核完成时间。"); - - b.Property("Reason") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("申请原因。"); - - b.Property("RefundNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("退款单号。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("用户提交时间。"); - - b.Property("ReviewNotes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "RefundNo") - .IsUnique(); - - b.ToTable("refund_requests", null, t => - { - t.HasComment("售后/退款申请。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("支付金额。"); - - b.Property("ChannelTransactionId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方渠道单号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Method") - .HasColumnType("integer") - .HasComment("支付方式。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付完成时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始回调内容。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("错误/备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TradeNo") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("平台交易号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("payment_records", null, t => - { - t.HasComment("支付流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRefundRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("退款金额。"); - - b.Property("ChannelRefundId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("渠道退款流水号。"); - - b.Property("CompletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("渠道返回的原始数据 JSON。"); - - b.Property("PaymentRecordId") - .HasColumnType("bigint") - .HasComment("原支付记录标识。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("退款请求时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PaymentRecordId"); - - b.ToTable("payment_refund_records", null, t => - { - t.HasComment("支付渠道退款流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.Product", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CategoryId") - .HasColumnType("bigint") - .HasComment("所属分类。"); - - b.Property("CoverImage") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("主图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("商品描述。"); - - b.Property("EnableDelivery") - .HasColumnType("boolean") - .HasComment("支持配送。"); - - b.Property("EnableDineIn") - .HasColumnType("boolean") - .HasComment("支持堂食。"); - - b.Property("EnablePickup") - .HasColumnType("boolean") - .HasComment("支持自提。"); - - b.Property("GalleryImages") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Gallery 图片逗号分隔。"); - - b.Property("IsFeatured") - .HasColumnType("boolean") - .HasComment("是否热门推荐。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("最大每单限购。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("现价。"); - - b.Property("SpuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("商品编码。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("商品状态。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("库存数量(可选)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("Subtitle") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("副标题/卖点。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("售卖单位(份/杯等)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SpuCode") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("products", null, t => - { - t.HasComment("商品(SPU)信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("MaxSelect") - .HasColumnType("integer") - .HasComment("最大选择数量。"); - - b.Property("MinSelect") - .HasColumnType("integer") - .HasComment("最小选择数量。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "Name"); - - b.ToTable("product_addon_groups", null, t => - { - t.HasComment("加料/做法分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AddonGroupId") - .HasColumnType("bigint") - .HasComment("所属加料分组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选项。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("product_addon_options", null, t => - { - t.HasComment("加料选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称,例如“辣度”“份量”。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型(单选/多选)。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("显示排序。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店,可为空表示所有门店共享。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("product_attribute_groups", null, t => - { - t.HasComment("商品规格/属性分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributeGroupId") - .HasColumnType("bigint") - .HasComment("所属规格组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选中。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AttributeGroupId", "Name") - .IsUnique(); - - b.ToTable("product_attribute_options", null, t => - { - t.HasComment("商品规格选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("分类描述。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分类名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("product_categories", null, t => - { - t.HasComment("商品分类。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductMediaAsset", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Caption") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述或标题。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MediaType") - .HasColumnType("integer") - .HasComment("媒体类型。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品标识。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Url") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("媒资链接。"); - - b.HasKey("Id"); - - b.ToTable("product_media_assets", null, t => - { - t.HasComment("商品媒资素材。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductPricingRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("条件描述(JSON),如会员等级、渠道等。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效结束时间。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("特殊价格。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("RuleType") - .HasColumnType("integer") - .HasComment("策略类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StartTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效开始时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("WeekdaysJson") - .HasColumnType("text") - .HasComment("生效星期(JSON 数组)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "RuleType"); - - b.ToTable("product_pricing_rules", null, t => - { - t.HasComment("商品价格策略,支持会员价/时段价等。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductSku", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("规格属性 JSON(记录选项 ID)。"); - - b.Property("Barcode") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("条形码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("售价。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SkuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("SKU 编码。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("可售库存。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weight") - .HasPrecision(10, 3) - .HasColumnType("numeric(10,3)") - .HasComment("重量(千克)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SkuCode") - .IsUnique(); - - b.ToTable("product_skus", null, t => - { - t.HasComment("商品 SKU,记录具体规格组合价格。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Queues.Entities.QueueTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CalledAt") - .HasColumnType("timestamp with time zone") - .HasComment("叫号时间。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedWaitMinutes") - .HasColumnType("integer") - .HasComment("预计等待分钟。"); - - b.Property("ExpiredAt") - .HasColumnType("timestamp with time zone") - .HasComment("过号时间。"); - - b.Property("PartySize") - .HasColumnType("integer") - .HasComment("就餐人数。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("获取或设置所属门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNumber") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.HasIndex("TenantId", "StoreId", "TicketNumber") - .IsUnique(); - - b.ToTable("queue_tickets", null, t => - { - t.HasComment("排队叫号。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Reservations.Entities.Reservation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CheckInCode") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("核销码/到店码。"); - - b.Property("CheckedInAt") - .HasColumnType("timestamp with time zone") - .HasComment("实际签到时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("客户姓名。"); - - b.Property("CustomerPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PeopleCount") - .HasColumnType("integer") - .HasComment("用餐人数。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("预约号。"); - - b.Property("ReservationTime") - .HasColumnType("timestamp with time zone") - .HasComment("预约时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TablePreference") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌型/标签。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ReservationNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("reservations", null, t => - { - t.HasComment("预约/预订记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.Store", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ActivatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核通过时间。"); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("Announcement") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("门店公告。"); - - b.Property("AuditStatus") - .HasColumnType("integer") - .HasComment("审核状态。"); - - b.Property("BusinessHours") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("门店营业时段描述(备用字符串)。"); - - b.Property("BusinessLicenseImageUrl") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("门店营业执照图片地址(主体不一致模式使用)。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(50) - .HasColumnType("character varying(50)") - .HasComment("门店营业执照号(主体不一致模式使用)。"); - - b.Property("BusinessStatus") - .HasColumnType("integer") - .HasComment("经营状态。"); - - b.Property("CategoryId") - .HasColumnType("bigint") - .HasComment("行业类目 ID。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("ClosureReason") - .HasColumnType("integer") - .HasComment("歇业原因。"); - - b.Property("ClosureReasonText") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("歇业原因补充说明。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("门店编码,便于扫码及外部对接。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家或地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("门店海报。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryRadiusKm") - .HasPrecision(6, 2) - .HasColumnType("numeric(6,2)") - .HasComment("默认配送半径(公里)。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("门店描述或公告。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区县信息。"); - - b.Property("ForceCloseReason") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("强制关闭原因。"); - - b.Property("ForceClosedAt") - .HasColumnType("timestamp with time zone") - .HasComment("强制关闭时间。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("LegalRepresentative") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasComment("门店法人(主体不一致模式使用)。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("高德/腾讯地图经度。"); - - b.Property("ManagerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("门店负责人姓名。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("门店名称。"); - - b.Property("OwnershipType") - .HasColumnType("integer") - .HasComment("主体类型。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("RegisteredAddress") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("门店注册地址(主体不一致模式使用)。"); - - b.Property("RejectionReason") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("审核驳回原因。"); - - b.Property("SignboardImageUrl") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("门头招牌图 URL。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("门店当前运营状态。"); - - b.Property("SubmittedAt") - .HasColumnType("timestamp with time zone") - .HasComment("提交审核时间。"); - - b.Property("SupportsDelivery") - .HasColumnType("boolean") - .HasComment("是否支持配送。"); - - b.Property("SupportsDineIn") - .HasColumnType("boolean") - .HasComment("是否支持堂食。"); - - b.Property("SupportsPickup") - .HasColumnType("boolean") - .HasComment("是否支持自提。"); - - b.Property("SupportsQueueing") - .HasColumnType("boolean") - .HasComment("支持排队叫号。"); - - b.Property("SupportsReservation") - .HasColumnType("boolean") - .HasComment("支持预约。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("门店标签(逗号分隔)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("Longitude", "Latitude") - .HasFilter("\"Longitude\" IS NOT NULL AND \"Latitude\" IS NOT NULL"); - - b.HasIndex("MerchantId", "BusinessLicenseNumber") - .IsUnique() - .HasFilter("\"BusinessLicenseNumber\" IS NOT NULL AND \"Status\" <> 3"); - - b.HasIndex("TenantId", "AuditStatus"); - - b.HasIndex("TenantId", "BusinessStatus"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.HasIndex("TenantId", "MerchantId"); - - b.HasIndex("TenantId", "OwnershipType"); - - b.ToTable("stores", null, t => - { - t.HasComment("门店信息,承载营业配置与能力。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreAuditRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("操作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("NewStatus") - .HasColumnType("integer") - .HasComment("操作后状态。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasComment("操作人名称。"); - - b.Property("PreviousStatus") - .HasColumnType("integer") - .HasComment("操作前状态。"); - - b.Property("RejectionReason") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("驳回理由文本。"); - - b.Property("RejectionReasonId") - .HasColumnType("bigint") - .HasComment("驳回理由 ID。"); - - b.Property("Remarks") - .HasMaxLength(1000) - .HasColumnType("character varying(1000)") - .HasComment("备注。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("CreatedAt"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("store_audit_records", null, t => - { - t.HasComment("门店审核记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreBusinessHour", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CapacityLimit") - .HasColumnType("integer") - .HasComment("最大接待容量或单量限制。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DayOfWeek") - .HasColumnType("integer") - .HasComment("星期几,0 表示周日。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间(本地时间)。"); - - b.Property("HourType") - .HasColumnType("integer") - .HasComment("时段类型(正常营业、休息、预约等)。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间(本地时间)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "DayOfWeek"); - - b.ToTable("store_business_hours", null, t => - { - t.HasComment("门店营业时段配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreDeliveryZone", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("EstimatedMinutes") - .HasColumnType("integer") - .HasComment("预计送达分钟。"); - - b.Property("MinimumOrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("起送价。"); - - b.Property("PolygonGeoJson") - .IsRequired() - .HasColumnType("text") - .HasComment("GeoJSON 表示的多边形范围。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ZoneName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ZoneName"); - - b.ToTable("store_delivery_zones", null, t => - { - t.HasComment("门店配送范围配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreEmployeeShift", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("排班角色。"); - - b.Property("ShiftDate") - .HasColumnType("timestamp with time zone") - .HasComment("班次日期。"); - - b.Property("StaffId") - .HasColumnType("bigint") - .HasComment("员工标识。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ShiftDate", "StaffId") - .IsUnique(); - - b.ToTable("store_employee_shifts", null, t => - { - t.HasComment("门店员工排班记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreFee", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BaseDeliveryFee") - .HasPrecision(10, 2) - .HasColumnType("numeric(10,2)") - .HasComment("基础配送费(元)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("FixedPackagingFee") - .HasPrecision(10, 2) - .HasColumnType("numeric(10,2)") - .HasComment("固定打包费(总计模式有效)。"); - - b.Property("FreeDeliveryThreshold") - .HasPrecision(10, 2) - .HasColumnType("numeric(10,2)") - .HasComment("免配送费门槛。"); - - b.Property("MinimumOrderAmount") - .HasPrecision(10, 2) - .HasColumnType("numeric(10,2)") - .HasComment("起送费(元)。"); - - b.Property("PackagingFeeMode") - .HasColumnType("integer") - .HasComment("打包费模式。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "StoreId") - .IsUnique(); - - b.ToTable("store_fees", null, t => - { - t.HasComment("门店费用配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreHoliday", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Date") - .HasColumnType("timestamp with time zone") - .HasComment("日期。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsClosed") - .HasColumnType("boolean") - .HasComment("是否全天闭店。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("说明内容。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Date") - .IsUnique(); - - b.ToTable("store_holidays", null, t => - { - t.HasComment("门店休息日或特殊营业日。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSetting", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowDaysAhead") - .HasColumnType("integer") - .HasComment("可预约天数(含当天)。"); - - b.Property("AllowToday") - .HasColumnType("boolean") - .HasComment("是否允许当天自提。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultCutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("默认截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单笔自提最大份数。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId") - .IsUnique(); - - b.ToTable("store_pickup_settings", null, t => - { - t.HasComment("门店自提配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSlot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("容量(份数)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("当天结束时间(UTC)。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("档期名称。"); - - b.Property("ReservedCount") - .HasColumnType("integer") - .HasComment("已占用数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("当天开始时间(UTC)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weekdays") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("适用星期(逗号分隔 1-7)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("store_pickup_slots", null, t => - { - t.HasComment("门店自提档期。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreQualification", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DocumentNumber") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasComment("证照编号。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期日期。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("证照文件 URL。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签发日期。"); - - b.Property("QualificationType") - .HasColumnType("integer") - .HasComment("资质类型。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(100) - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("ExpiresAt") - .HasFilter("\"ExpiresAt\" IS NOT NULL"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("store_qualifications", null, t => - { - t.HasComment("门店资质证照。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTable", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AreaId") - .HasColumnType("bigint") - .HasComment("所在区域 ID。"); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("可容纳人数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("QrCodeUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("桌码二维码地址。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前桌台状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("桌码。"); - - b.Property("Tags") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("桌台标签(堂食、快餐等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "TableCode") - .IsUnique(); - - b.ToTable("store_tables", null, t => - { - t.HasComment("桌台信息与二维码绑定。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTableArea", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("区域描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name") - .IsUnique(); - - b.ToTable("store_table_areas", null, t => - { - t.HasComment("门店桌台区域配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.QuotaPackage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("描述。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否上架。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("配额包名称。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("价格。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型。"); - - b.Property("QuotaValue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配额数值。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("排序。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("QuotaType", "IsActive", "SortOrder"); - - b.ToTable("quota_packages", null, t => - { - t.HasComment("配额包定义(平台提供的可购买配额包)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.Tenant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("text") - .HasComment("详细地址信息。"); - - b.Property("City") - .HasColumnType("text") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("租户短编码,作为跨系统引用的唯一标识。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("主联系人邮箱。"); - - b.Property("ContactName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("主联系人姓名。"); - - b.Property("ContactPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("主联系人电话。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家/地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("品牌海报或封面图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("服务生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("服务到期时间(UTC)。"); - - b.Property("Industry") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所属行业,如餐饮、零售等。"); - - b.Property("LegalEntityName") - .HasColumnType("text") - .HasComment("法人或公司主体名称。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("LOGO 图片地址。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("租户全称或品牌名称。"); - - b.Property("OperatingMode") - .HasColumnType("integer") - .HasComment("经营模式(同一主体/不同主体)。"); - - b.Property("PrimaryOwnerUserId") - .HasColumnType("bigint") - .HasComment("系统内对应的租户所有者账号 ID。"); - - b.Property("Province") - .HasColumnType("text") - .HasComment("所在省份或州。"); - - b.Property("Remarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息,用于运营记录特殊说明。"); - - b.Property("ShortName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("对外展示的简称。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("租户当前状态,涵盖审核、启用、停用等场景。"); - - b.Property("SuspendedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次暂停服务时间。"); - - b.Property("SuspensionReason") - .HasColumnType("text") - .HasComment("暂停或终止的原因说明。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("业务标签集合(逗号分隔)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Website") - .HasColumnType("text") - .HasComment("官网或主要宣传链接。"); - - b.HasKey("Id"); - - b.HasIndex("Code") - .IsUnique(); - - b.HasIndex("ContactPhone") - .IsUnique(); - - b.ToTable("tenants", null, t => - { - t.HasComment("平台租户信息,描述租户的生命周期与基础资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementType") - .HasColumnType("integer") - .HasComment("公告类型。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("公告正文(可为 Markdown/HTML,前端自行渲染)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("失效时间(UTC),为空表示长期有效。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否启用(已弃用,迁移期保留)。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("展示优先级,数值越大越靠前。"); - - b.Property("PublishedAt") - .HasColumnType("timestamp with time zone") - .HasComment("实际发布时间(UTC)。"); - - b.Property("PublisherScope") - .HasColumnType("integer") - .HasComment("发布者范围。"); - - b.Property("PublisherUserId") - .HasColumnType("bigint") - .HasComment("发布者用户 ID(平台或租户后台账号)。"); - - b.Property("RevokedAt") - .HasColumnType("timestamp with time zone") - .HasComment("撤销时间(UTC)。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("ScheduledPublishAt") - .HasColumnType("timestamp with time zone") - .HasComment("预定发布时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("公告状态。"); - - b.Property("TargetParameters") - .HasColumnType("text") - .HasComment("目标受众参数(JSON)。"); - - b.Property("TargetType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("目标受众类型。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("公告标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("Status", "EffectiveFrom") - .HasFilter("\"TenantId\" = 0"); - - b.HasIndex("TenantId", "AnnouncementType", "IsActive"); - - b.HasIndex("TenantId", "EffectiveFrom", "EffectiveTo"); - - b.HasIndex("TenantId", "Status", "EffectiveFrom"); - - b.ToTable("tenant_announcements", null, t => - { - t.HasComment("租户公告。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncementRead", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementId") - .HasColumnType("bigint") - .HasComment("公告 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("已读时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("已读用户 ID(后台账号),为空表示租户级已读。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AnnouncementId", "UserId") - .IsUnique(); - - b.ToTable("tenant_announcement_reads", null, t => - { - t.HasComment("租户公告已读记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantBillingStatement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AmountDue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额(原始金额)。"); - - b.Property("AmountPaid") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("BillingType") - .HasColumnType("integer") - .HasComment("账单类型(订阅账单/配额包账单/手动账单/续费账单)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Currency") - .IsRequired() - .ValueGeneratedOnAdd() - .HasMaxLength(8) - .HasColumnType("character varying(8)") - .HasDefaultValue("CNY") - .HasComment("货币类型(默认 CNY)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("折扣金额。"); - - b.Property("DueDate") - .HasColumnType("timestamp with time zone") - .HasComment("到期日。"); - - b.Property("LineItemsJson") - .HasColumnType("text") - .HasComment("账单明细 JSON,记录各项费用。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息(如:人工备注、取消原因等)。"); - - b.Property("OverdueNotifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("逾期通知时间。"); - - b.Property("PeriodEnd") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期结束时间。"); - - b.Property("PeriodStart") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期开始时间。"); - - b.Property("ReminderSentAt") - .HasColumnType("timestamp with time zone") - .HasComment("提醒发送时间(续费提醒、逾期提醒等)。"); - - b.Property("StatementNo") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("账单编号,供对账查询。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前付款状态。"); - - b.Property("SubscriptionId") - .HasColumnType("bigint") - .HasComment("关联的订阅 ID(仅当 BillingType 为 Subscription 或 Renewal 时有值)。"); - - b.Property("TaxAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("税费金额。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("CreatedAt") - .HasDatabaseName("idx_billing_created_at"); - - b.HasIndex("Status", "DueDate") - .HasDatabaseName("idx_billing_status_duedate") - .HasFilter("\"Status\" IN (0, 2)"); - - b.HasIndex("TenantId", "StatementNo") - .IsUnique(); - - b.HasIndex("TenantId", "Status", "DueDate") - .HasDatabaseName("idx_billing_tenant_status_duedate"); - - b.ToTable("tenant_billing_statements", null, t => - { - t.HasComment("租户账单,用于呈现周期性收费。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantNotification", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("发布通道(站内、邮件、短信等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("通知正文。"); - - b.Property("MetadataJson") - .HasColumnType("text") - .HasComment("附加元数据 JSON。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("租户是否已阅读。"); - - b.Property("SentAt") - .HasColumnType("timestamp with time zone") - .HasComment("推送时间。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("通知重要级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("通知标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Channel", "SentAt"); - - b.ToTable("tenant_notifications", null, t => - { - t.HasComment("面向租户的站内通知或消息推送。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantPackage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("套餐描述,包含适用场景、权益等。"); - - b.Property("FeaturePoliciesJson") - .HasColumnType("text") - .HasComment("权益明细 JSON,记录自定义特性开关。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否仍启用(平台控制)。"); - - b.Property("IsAllowNewTenantPurchase") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否允许新租户购买/选择(仅影响新购)。"); - - b.Property("IsPublicVisible") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否对外可见(展示页/套餐列表可见性)。"); - - b.Property("IsRecommended") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false) - .HasComment("是否推荐展示(运营推荐标识)。"); - - b.Property("MaxAccountCount") - .HasColumnType("integer") - .HasComment("允许创建的最大账号数。"); - - b.Property("MaxDeliveryOrders") - .HasColumnType("integer") - .HasComment("每月可调用的配送单数量上限。"); - - b.Property("MaxSmsCredits") - .HasColumnType("integer") - .HasComment("每月短信额度上限。"); - - b.Property("MaxStorageGb") - .HasColumnType("integer") - .HasComment("存储容量上限(GB)。"); - - b.Property("MaxStoreCount") - .HasColumnType("integer") - .HasComment("允许的最大门店数。"); - - b.Property("MonthlyPrice") - .HasColumnType("numeric") - .HasComment("月付价格,单位:人民币元。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("套餐名称,展示给租户的简称。"); - - b.Property("PackageType") - .HasColumnType("integer") - .HasComment("套餐分类(试用、标准、旗舰等)。"); - - b.Property("PublishStatus") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("发布状态:0=草稿,1=已发布。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("展示排序,数值越小越靠前。"); - - b.PrimitiveCollection("Tags") - .IsRequired() - .HasColumnType("text[]") - .HasComment("套餐标签(用于展示与对比页)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("YearlyPrice") - .HasColumnType("numeric") - .HasComment("年付价格,单位:人民币元。"); - - b.HasKey("Id"); - - b.HasIndex("IsActive", "SortOrder"); - - b.HasIndex("PublishStatus", "IsActive", "IsPublicVisible", "IsAllowNewTenantPurchase", "SortOrder"); - - b.ToTable("tenant_packages", null, t => - { - t.HasComment("平台提供的租户套餐定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantPayment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("支付金额。"); - - b.Property("BillingStatementId") - .HasColumnType("bigint") - .HasComment("关联的账单 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Method") - .HasColumnType("integer") - .HasComment("支付方式。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付时间。"); - - b.Property("ProofUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("支付凭证 URL。"); - - b.Property("RefundReason") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("退款原因。"); - - b.Property("RefundedAt") - .HasColumnType("timestamp with time zone") - .HasComment("退款时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TransactionNo") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("交易号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("VerifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核时间。"); - - b.Property("VerifiedBy") - .HasColumnType("bigint") - .HasComment("审核人 ID(管理员)。"); - - b.HasKey("Id"); - - b.HasIndex("TransactionNo") - .HasDatabaseName("idx_payment_transaction_no") - .HasFilter("\"TransactionNo\" IS NOT NULL"); - - b.HasIndex("BillingStatementId", "PaidAt") - .HasDatabaseName("idx_payment_billing_paidat"); - - b.HasIndex("TenantId", "BillingStatementId"); - - b.ToTable("tenant_payments", null, t => - { - t.HasComment("租户支付记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaPackagePurchase", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiredAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(可选)。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("购买价格。"); - - b.Property("PurchasedAt") - .HasColumnType("timestamp with time zone") - .HasComment("购买时间。"); - - b.Property("QuotaPackageId") - .HasColumnType("bigint") - .HasComment("配额包 ID。"); - - b.Property("QuotaValue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("购买时的配额值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "QuotaPackageId", "PurchasedAt"); - - b.ToTable("tenant_quota_package_purchases", null, t => - { - t.HasComment("租户配额包购买记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaUsage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LastResetAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次重置时间。"); - - b.Property("LimitValue") - .HasColumnType("numeric") - .HasComment("当前配额上限。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型,例如门店数、短信条数等。"); - - b.Property("ResetCycle") - .HasColumnType("text") - .HasComment("配额刷新周期描述(如月、年)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedValue") - .HasColumnType("numeric") - .HasComment("已消耗的数量。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "QuotaType") - .IsUnique(); - - b.ToTable("tenant_quota_usages", null, t => - { - t.HasComment("租户配额使用情况快照。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaUsageHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChangeAmount") - .HasColumnType("numeric") - .HasComment("变更量(可选)。"); - - b.Property("ChangeReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("变更原因(可选)。"); - - b.Property("ChangeType") - .HasColumnType("integer") - .HasComment("变更类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LimitValue") - .HasColumnType("numeric") - .HasComment("限额值(记录时刻的快照)。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型。"); - - b.Property("RecordedAt") - .HasColumnType("timestamp with time zone") - .HasComment("记录时间(UTC)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedValue") - .HasColumnType("numeric") - .HasComment("已使用值(记录时刻的快照)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "RecordedAt"); - - b.HasIndex("TenantId", "QuotaType", "RecordedAt"); - - b.ToTable("tenant_quota_usage_histories", null, t => - { - t.HasComment("租户配额使用历史记录(用于追踪配额上下限与使用量的时间序列变化)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantReviewClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ClaimedAt") - .HasColumnType("timestamp with time zone") - .HasComment("领取时间(UTC)。"); - - b.Property("ClaimedBy") - .HasColumnType("bigint") - .HasComment("领取人用户 ID。"); - - b.Property("ClaimedByName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("领取人名称(展示用快照)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReleasedAt") - .HasColumnType("timestamp with time zone") - .HasComment("释放时间(UTC),未释放时为 null。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("被领取的租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("ClaimedBy"); - - b.HasIndex("TenantId") - .IsUnique() - .HasFilter("\"ReleasedAt\" IS NULL AND \"DeletedAt\" IS NULL"); - - b.ToTable("tenant_review_claims", null, t => - { - t.HasComment("租户入驻审核领取记录(防止多管理员并发审核)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscription", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AutoRenew") - .HasColumnType("boolean") - .HasComment("是否开启自动续费。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("订阅生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("订阅到期时间(UTC)。"); - - b.Property("NextBillingDate") - .HasColumnType("timestamp with time zone") - .HasComment("下一个计费时间,配合自动续费使用。"); - - b.Property("Notes") - .HasColumnType("text") - .HasComment("运营备注信息。"); - - b.Property("ScheduledPackageId") - .HasColumnType("bigint") - .HasComment("若已排期升降配,对应的新套餐 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("订阅当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TenantPackageId") - .HasColumnType("bigint") - .HasComment("当前订阅关联的套餐标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantPackageId"); - - b.ToTable("tenant_subscriptions", null, t => - { - t.HasComment("租户套餐订阅记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscriptionHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasColumnType("numeric") - .HasComment("相关费用。"); - - b.Property("ChangeType") - .HasColumnType("integer") - .HasComment("变更类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Currency") - .HasMaxLength(8) - .HasColumnType("character varying(8)") - .HasComment("币种。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("FromPackageId") - .HasColumnType("bigint") - .HasComment("原套餐 ID。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("租户标识。"); - - b.Property("TenantSubscriptionId") - .HasColumnType("bigint") - .HasComment("对应的订阅 ID。"); - - b.Property("ToPackageId") - .HasColumnType("bigint") - .HasComment("新套餐 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantSubscriptionId"); - - b.ToTable("tenant_subscription_histories", null, t => - { - t.HasComment("租户套餐订阅变更记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantVerificationProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdditionalDataJson") - .HasColumnType("text") - .HasComment("附加资料(JSON)。"); - - b.Property("BankAccountName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("开户名。"); - - b.Property("BankAccountNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("银行账号。"); - - b.Property("BankName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("银行名称。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照编号。"); - - b.Property("BusinessLicenseUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营业执照文件地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LegalPersonIdBackUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证反面。"); - - b.Property("LegalPersonIdFrontUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证正面。"); - - b.Property("LegalPersonIdNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("法人身份证号。"); - - b.Property("LegalPersonName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人姓名。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注。"); - - b.Property("ReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核时间。"); - - b.Property("ReviewedBy") - .HasColumnType("bigint") - .HasComment("审核人 ID。"); - - b.Property("ReviewedByName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("审核人姓名。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("实名状态。"); - - b.Property("SubmittedAt") - .HasColumnType("timestamp with time zone") - .HasComment("提交时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("对应的租户标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId") - .IsUnique(); - - b.ToTable("tenant_verification_profiles", null, t => - { - t.HasComment("租户实名认证资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.HasOne("TakeoutSaaS.Domain.Orders.Entities.Order", null) - .WithMany() - .HasForeignKey("OrderId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251231124137_AddStoreManagementEntities.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251231124137_AddStoreManagementEntities.cs deleted file mode 100644 index 15d415d..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20251231124137_AddStoreManagementEntities.cs +++ /dev/null @@ -1,319 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - /// - public partial class AddStoreManagementEntities : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "ActivatedAt", - table: "stores", - type: "timestamp with time zone", - nullable: true, - comment: "审核通过时间。"); - - migrationBuilder.AddColumn( - name: "AuditStatus", - table: "stores", - type: "integer", - nullable: false, - defaultValue: 0, - comment: "审核状态。"); - - migrationBuilder.AddColumn( - name: "BusinessStatus", - table: "stores", - type: "integer", - nullable: false, - defaultValue: 0, - comment: "经营状态。"); - - migrationBuilder.AddColumn( - name: "CategoryId", - table: "stores", - type: "bigint", - nullable: true, - comment: "行业类目 ID。"); - - migrationBuilder.AddColumn( - name: "ClosureReason", - table: "stores", - type: "integer", - nullable: true, - comment: "歇业原因。"); - - migrationBuilder.AddColumn( - name: "ClosureReasonText", - table: "stores", - type: "character varying(500)", - maxLength: 500, - nullable: true, - comment: "歇业原因补充说明。"); - - migrationBuilder.AddColumn( - name: "ForceCloseReason", - table: "stores", - type: "character varying(500)", - maxLength: 500, - nullable: true, - comment: "强制关闭原因。"); - - migrationBuilder.AddColumn( - name: "ForceClosedAt", - table: "stores", - type: "timestamp with time zone", - nullable: true, - comment: "强制关闭时间。"); - - migrationBuilder.AddColumn( - name: "OwnershipType", - table: "stores", - type: "integer", - nullable: false, - defaultValue: 0, - comment: "主体类型。"); - - migrationBuilder.AddColumn( - name: "RejectionReason", - table: "stores", - type: "character varying(500)", - maxLength: 500, - nullable: true, - comment: "审核驳回原因。"); - - migrationBuilder.AddColumn( - name: "SignboardImageUrl", - table: "stores", - type: "character varying(500)", - maxLength: 500, - nullable: true, - comment: "门头招牌图 URL。"); - - migrationBuilder.AddColumn( - name: "SubmittedAt", - table: "stores", - type: "timestamp with time zone", - nullable: true, - comment: "提交审核时间。"); - - migrationBuilder.CreateTable( - name: "store_audit_records", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - StoreId = table.Column(type: "bigint", nullable: false, comment: "门店标识。"), - Action = table.Column(type: "integer", nullable: false, comment: "操作类型。"), - PreviousStatus = table.Column(type: "integer", nullable: true, comment: "操作前状态。"), - NewStatus = table.Column(type: "integer", nullable: false, comment: "操作后状态。"), - OperatorId = table.Column(type: "bigint", nullable: true, comment: "操作人 ID。"), - OperatorName = table.Column(type: "character varying(100)", maxLength: 100, nullable: false, comment: "操作人名称。"), - RejectionReasonId = table.Column(type: "bigint", nullable: true, comment: "驳回理由 ID。"), - RejectionReason = table.Column(type: "character varying(500)", maxLength: 500, nullable: true, comment: "驳回理由文本。"), - Remarks = table.Column(type: "character varying(1000)", maxLength: 1000, nullable: true, comment: "备注。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_store_audit_records", x => x.Id); - }, - comment: "门店审核记录。"); - - migrationBuilder.CreateTable( - name: "store_fees", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - StoreId = table.Column(type: "bigint", nullable: false, comment: "门店标识。"), - MinimumOrderAmount = table.Column(type: "numeric(10,2)", precision: 10, scale: 2, nullable: false, comment: "起送费(元)。"), - BaseDeliveryFee = table.Column(type: "numeric(10,2)", precision: 10, scale: 2, nullable: false, comment: "基础配送费(元)。"), - PackagingFeeMode = table.Column(type: "integer", nullable: false, comment: "打包费模式。"), - FixedPackagingFee = table.Column(type: "numeric(10,2)", precision: 10, scale: 2, nullable: false, comment: "固定打包费(总计模式有效)。"), - FreeDeliveryThreshold = table.Column(type: "numeric(10,2)", precision: 10, scale: 2, nullable: true, comment: "免配送费门槛。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_store_fees", x => x.Id); - }, - comment: "门店费用配置。"); - - migrationBuilder.CreateTable( - name: "store_qualifications", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - StoreId = table.Column(type: "bigint", nullable: false, comment: "门店标识。"), - QualificationType = table.Column(type: "integer", nullable: false, comment: "资质类型。"), - FileUrl = table.Column(type: "character varying(500)", maxLength: 500, nullable: false, comment: "证照文件 URL。"), - DocumentNumber = table.Column(type: "character varying(100)", maxLength: 100, nullable: true, comment: "证照编号。"), - IssuedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "签发日期。"), - ExpiresAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "到期日期。"), - SortOrder = table.Column(type: "integer", nullable: false, defaultValue: 100, comment: "排序值。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_store_qualifications", x => x.Id); - }, - comment: "门店资质证照。"); - - migrationBuilder.CreateIndex( - name: "IX_stores_Longitude_Latitude", - table: "stores", - columns: new[] { "Longitude", "Latitude" }, - filter: "\"Longitude\" IS NOT NULL AND \"Latitude\" IS NOT NULL"); - - migrationBuilder.CreateIndex( - name: "IX_stores_TenantId_AuditStatus", - table: "stores", - columns: new[] { "TenantId", "AuditStatus" }); - - migrationBuilder.CreateIndex( - name: "IX_stores_TenantId_BusinessStatus", - table: "stores", - columns: new[] { "TenantId", "BusinessStatus" }); - - migrationBuilder.CreateIndex( - name: "IX_stores_TenantId_OwnershipType", - table: "stores", - columns: new[] { "TenantId", "OwnershipType" }); - - migrationBuilder.CreateIndex( - name: "IX_store_audit_records_CreatedAt", - table: "store_audit_records", - column: "CreatedAt"); - - migrationBuilder.CreateIndex( - name: "IX_store_audit_records_TenantId_StoreId", - table: "store_audit_records", - columns: new[] { "TenantId", "StoreId" }); - - migrationBuilder.CreateIndex( - name: "IX_store_fees_TenantId", - table: "store_fees", - column: "TenantId"); - - migrationBuilder.CreateIndex( - name: "IX_store_fees_TenantId_StoreId", - table: "store_fees", - columns: new[] { "TenantId", "StoreId" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_store_qualifications_ExpiresAt", - table: "store_qualifications", - column: "ExpiresAt", - filter: "\"ExpiresAt\" IS NOT NULL"); - - migrationBuilder.CreateIndex( - name: "IX_store_qualifications_TenantId_StoreId", - table: "store_qualifications", - columns: new[] { "TenantId", "StoreId" }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "store_audit_records"); - - migrationBuilder.DropTable( - name: "store_fees"); - - migrationBuilder.DropTable( - name: "store_qualifications"); - - migrationBuilder.DropIndex( - name: "IX_stores_Longitude_Latitude", - table: "stores"); - - migrationBuilder.DropIndex( - name: "IX_stores_TenantId_AuditStatus", - table: "stores"); - - migrationBuilder.DropIndex( - name: "IX_stores_TenantId_BusinessStatus", - table: "stores"); - - migrationBuilder.DropIndex( - name: "IX_stores_TenantId_OwnershipType", - table: "stores"); - - migrationBuilder.DropColumn( - name: "ActivatedAt", - table: "stores"); - - migrationBuilder.DropColumn( - name: "AuditStatus", - table: "stores"); - - migrationBuilder.DropColumn( - name: "BusinessStatus", - table: "stores"); - - migrationBuilder.DropColumn( - name: "CategoryId", - table: "stores"); - - migrationBuilder.DropColumn( - name: "ClosureReason", - table: "stores"); - - migrationBuilder.DropColumn( - name: "ClosureReasonText", - table: "stores"); - - migrationBuilder.DropColumn( - name: "ForceCloseReason", - table: "stores"); - - migrationBuilder.DropColumn( - name: "ForceClosedAt", - table: "stores"); - - migrationBuilder.DropColumn( - name: "OwnershipType", - table: "stores"); - - migrationBuilder.DropColumn( - name: "RejectionReason", - table: "stores"); - - migrationBuilder.DropColumn( - name: "SignboardImageUrl", - table: "stores"); - - migrationBuilder.DropColumn( - name: "SubmittedAt", - table: "stores"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20260120045054_ChangeStoreQualificationDateColumns.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20260120045054_ChangeStoreQualificationDateColumns.Designer.cs deleted file mode 100644 index 6a13bb2..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20260120045054_ChangeStoreQualificationDateColumns.Designer.cs +++ /dev/null @@ -1,7391 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.App.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - [DbContext(typeof(TakeoutAppDbContext))] - [Migration("20260120045054_ChangeStoreQualificationDateColumns")] - partial class ChangeStoreQualificationDateColumns - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.1") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricAlertRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionJson") - .IsRequired() - .HasColumnType("text") - .HasComment("触发条件 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Enabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("关联指标。"); - - b.Property("NotificationChannels") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("通知渠道。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("告警级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "Severity"); - - b.ToTable("metric_alert_rules", null, t => - { - t.HasComment("指标告警规则。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricDefinition", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("指标编码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultAggregation") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("默认聚合方式。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("说明。"); - - b.Property("DimensionsJson") - .HasColumnType("text") - .HasComment("维度描述 JSON。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("指标名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("metric_definitions", null, t => - { - t.HasComment("指标定义,描述可观测的数据点。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricSnapshot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DimensionKey") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("维度键(JSON)。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("指标定义 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Value") - .HasPrecision(18, 4) - .HasColumnType("numeric(18,4)") - .HasComment("数值。"); - - b.Property("WindowEnd") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口结束。"); - - b.Property("WindowStart") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口开始。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "DimensionKey", "WindowStart", "WindowEnd") - .IsUnique(); - - b.ToTable("metric_snapshots", null, t => - { - t.HasComment("指标快照,用于大盘展示。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.Coupon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("券码或序列号。"); - - b.Property("CouponTemplateId") - .HasColumnType("bigint") - .HasComment("模板标识。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("发放时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID(已使用时记录)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedAt") - .HasColumnType("timestamp with time zone") - .HasComment("使用时间。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("归属用户。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("coupons", null, t => - { - t.HasComment("用户领取的券。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.CouponTemplate", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowStack") - .HasColumnType("boolean") - .HasComment("是否允许叠加其他优惠。"); - - b.Property("ChannelsJson") - .HasColumnType("text") - .HasComment("发放渠道(JSON)。"); - - b.Property("ClaimedQuantity") - .HasColumnType("integer") - .HasComment("已领取数量。"); - - b.Property("CouponType") - .HasColumnType("integer") - .HasComment("券类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("DiscountCap") - .HasColumnType("numeric") - .HasComment("折扣上限(针对折扣券)。"); - - b.Property("MinimumSpend") - .HasColumnType("numeric") - .HasComment("最低消费门槛。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("模板名称。"); - - b.Property("ProductScopeJson") - .HasColumnType("text") - .HasComment("适用品类或商品范围(JSON)。"); - - b.Property("RelativeValidDays") - .HasColumnType("integer") - .HasComment("有效天数(相对发放时间)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreScopeJson") - .HasColumnType("text") - .HasComment("适用门店 ID 集合(JSON)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TotalQuantity") - .HasColumnType("integer") - .HasComment("总发放数量上限。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ValidFrom") - .HasColumnType("timestamp with time zone") - .HasComment("可用开始时间。"); - - b.Property("ValidTo") - .HasColumnType("timestamp with time zone") - .HasComment("可用结束时间。"); - - b.Property("Value") - .HasColumnType("numeric") - .HasComment("面值或折扣额度。"); - - b.HasKey("Id"); - - b.ToTable("coupon_templates", null, t => - { - t.HasComment("优惠券模板。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.PromotionCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AudienceDescription") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("目标人群描述。"); - - b.Property("BannerUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营销素材(如 banner)。"); - - b.Property("Budget") - .HasColumnType("numeric") - .HasComment("预算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("PromotionType") - .HasColumnType("integer") - .HasComment("活动类型。"); - - b.Property("RulesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("活动规则 JSON。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("活动状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("promotion_campaigns", null, t => - { - t.HasComment("营销活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChatSessionId") - .HasColumnType("bigint") - .HasComment("会话标识。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("消息内容。"); - - b.Property("ContentType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("消息类型(文字/图片/语音等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRead") - .HasColumnType("boolean") - .HasComment("是否已读。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("读取时间。"); - - b.Property("SenderType") - .HasColumnType("integer") - .HasComment("发送方类型。"); - - b.Property("SenderUserId") - .HasColumnType("bigint") - .HasComment("发送方用户 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ChatSessionId", "CreatedAt"); - - b.ToTable("chat_messages", null, t => - { - t.HasComment("会话消息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AgentUserId") - .HasColumnType("bigint") - .HasComment("当前客服员工 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("顾客用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndedAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("IsBotActive") - .HasColumnType("boolean") - .HasComment("是否机器人接待中。"); - - b.Property("SessionCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话编号。"); - - b.Property("StartedAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店(可空为平台)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionCode") - .IsUnique(); - - b.ToTable("chat_sessions", null, t => - { - t.HasComment("客服会话。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.SupportTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AssignedAgentId") - .HasColumnType("bigint") - .HasComment("指派的客服。"); - - b.Property("ClosedAt") - .HasColumnType("timestamp with time zone") - .HasComment("关闭时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("客户用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .IsRequired() - .HasColumnType("text") - .HasComment("工单详情。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单(如有)。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("优先级。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("Subject") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("工单主题。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("工单编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TicketNo") - .IsUnique(); - - b.ToTable("support_tickets", null, t => - { - t.HasComment("客服工单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.TicketComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttachmentsJson") - .HasColumnType("text") - .HasComment("附件 JSON。"); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人 ID。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsInternal") - .HasColumnType("boolean") - .HasComment("是否内部备注。"); - - b.Property("SupportTicketId") - .HasColumnType("bigint") - .HasComment("工单标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SupportTicketId"); - - b.ToTable("ticket_comments", null, t => - { - t.HasComment("工单评论/流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryEvent", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryOrderId") - .HasColumnType("bigint") - .HasComment("配送单标识。"); - - b.Property("EventType") - .HasColumnType("integer") - .HasComment("事件类型。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("事件描述。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始数据 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DeliveryOrderId", "EventType"); - - b.ToTable("delivery_events", null, t => - { - t.HasComment("配送状态事件流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CourierName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("骑手姓名。"); - - b.Property("CourierPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("骑手电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveredAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("DispatchedAt") - .HasColumnType("timestamp with time zone") - .HasComment("下发时间。"); - - b.Property("FailureReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("异常原因。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("获取或设置关联订单 ID。"); - - b.Property("PickedUpAt") - .HasColumnType("timestamp with time zone") - .HasComment("取餐时间。"); - - b.Property("Provider") - .HasColumnType("integer") - .HasComment("配送服务商。"); - - b.Property("ProviderOrderId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方配送单号。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId") - .IsUnique(); - - b.ToTable("delivery_orders", null, t => - { - t.HasComment("配送单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliateOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("推广人标识。"); - - b.Property("BuyerUserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedCommission") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("预计佣金。"); - - b.Property("OrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("订单金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("SettledAt") - .HasColumnType("timestamp with time zone") - .HasComment("结算完成时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "OrderId") - .IsUnique(); - - b.ToTable("affiliate_orders", null, t => - { - t.HasComment("分销订单记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePartner", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChannelType") - .HasColumnType("integer") - .HasComment("渠道类型。"); - - b.Property("CommissionRate") - .HasColumnType("numeric") - .HasComment("分成比例(0-1)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称或渠道名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID(如绑定平台账号)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DisplayName"); - - b.ToTable("affiliate_partners", null, t => - { - t.HasComment("分销/推广合作伙伴。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePayout", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("合作伙伴标识。"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("结算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("打款时间。"); - - b.Property("Period") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("结算周期描述。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "Period") - .IsUnique(); - - b.ToTable("affiliate_payouts", null, t => - { - t.HasComment("佣金结算记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowMakeupCount") - .HasColumnType("integer") - .HasComment("支持补签次数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("活动描述。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("结束日期。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("RewardsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("连签奖励 JSON。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("开始日期。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name"); - - b.ToTable("checkin_campaigns", null, t => - { - t.HasComment("签到活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CheckInCampaignId") - .HasColumnType("bigint") - .HasComment("活动标识。"); - - b.Property("CheckInDate") - .HasColumnType("timestamp with time zone") - .HasComment("签到日期(本地)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsMakeup") - .HasColumnType("boolean") - .HasComment("是否补签。"); - - b.Property("RewardJson") - .IsRequired() - .HasColumnType("text") - .HasComment("获得奖励 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "CheckInCampaignId", "UserId", "CheckInDate") - .IsUnique(); - - b.ToTable("checkin_records", null, t => - { - t.HasComment("用户签到记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsDeleted") - .HasColumnType("boolean") - .HasComment("状态。"); - - b.Property("ParentId") - .HasColumnType("bigint") - .HasComment("父级评论 ID。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "CreatedAt"); - - b.ToTable("community_comments", null, t => - { - t.HasComment("社区评论。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityPost", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("作者用户 ID。"); - - b.Property("CommentCount") - .HasColumnType("integer") - .HasComment("评论数。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LikeCount") - .HasColumnType("integer") - .HasComment("点赞数。"); - - b.Property("MediaJson") - .HasColumnType("text") - .HasComment("媒体资源 JSON。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AuthorUserId", "CreatedAt"); - - b.ToTable("community_posts", null, t => - { - t.HasComment("社区动态。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityReaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态 ID。"); - - b.Property("ReactedAt") - .HasColumnType("timestamp with time zone") - .HasComment("时间戳。"); - - b.Property("ReactionType") - .HasColumnType("integer") - .HasComment("反应类型。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "UserId") - .IsUnique(); - - b.ToTable("community_reactions", null, t => - { - t.HasComment("社区互动反馈。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentCount") - .HasColumnType("integer") - .HasComment("当前已参与人数。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("GroupOrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("拼单编号。"); - - b.Property("GroupPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("拼团价格。"); - - b.Property("LeaderUserId") - .HasColumnType("bigint") - .HasComment("团长用户 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("关联商品或套餐。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("拼团状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("SucceededAt") - .HasColumnType("timestamp with time zone") - .HasComment("成团时间。"); - - b.Property("TargetCount") - .HasColumnType("integer") - .HasComment("成团需要的人数。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderNo") - .IsUnique(); - - b.ToTable("group_orders", null, t => - { - t.HasComment("拼单活动。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupParticipant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GroupOrderId") - .HasColumnType("bigint") - .HasComment("拼单活动标识。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("参与时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("对应订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("参与状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderId", "UserId") - .IsUnique(); - - b.ToTable("group_participants", null, t => - { - t.HasComment("拼单参与者。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryAdjustment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdjustmentType") - .HasColumnType("integer") - .HasComment("调整类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("InventoryItemId") - .HasColumnType("bigint") - .HasComment("对应的库存记录标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("调整数量,正数增加,负数减少。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("原因说明。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "InventoryItemId", "OccurredAt"); - - b.ToTable("inventory_adjustments", null, t => - { - t.HasComment("库存调整记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryBatch", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("ProductionDate") - .HasColumnType("timestamp with time zone") - .HasComment("生产日期。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("入库数量。"); - - b.Property("RemainingQuantity") - .HasColumnType("integer") - .HasComment("剩余数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber") - .IsUnique(); - - b.ToTable("inventory_batches", null, t => - { - t.HasComment("SKU 批次信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchConsumeStrategy") - .HasColumnType("integer") - .HasComment("批次扣减策略。"); - - b.Property("BatchNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号,可为空表示混批。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售商品。"); - - b.Property("IsSoldOut") - .HasColumnType("boolean") - .HasComment("是否标记售罄。"); - - b.Property("Location") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("储位或仓位信息。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单品限购(覆盖商品级 MaxQuantityPerOrder)。"); - - b.Property("PresaleCapacity") - .HasColumnType("integer") - .HasComment("预售名额(上限)。"); - - b.Property("PresaleEndTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售结束时间(UTC)。"); - - b.Property("PresaleLocked") - .HasColumnType("integer") - .HasComment("当前预售已锁定数量。"); - - b.Property("PresaleStartTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售开始时间(UTC)。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("QuantityOnHand") - .HasColumnType("integer") - .HasComment("可用库存。"); - - b.Property("QuantityReserved") - .HasColumnType("integer") - .HasComment("已锁定库存(订单占用)。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("SafetyStock") - .HasColumnType("integer") - .HasComment("安全库存阈值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber"); - - b.ToTable("inventory_items", null, t => - { - t.HasComment("SKU 在门店的库存信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryLockRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("IdempotencyKey") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("幂等键。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售锁定。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU ID。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("锁定数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("锁定状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "IdempotencyKey") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "Status"); - - b.ToTable("inventory_lock_records", null, t => - { - t.HasComment("库存锁定记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberPointLedger", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BalanceAfterChange") - .HasColumnType("integer") - .HasComment("变动后余额。"); - - b.Property("ChangeAmount") - .HasColumnType("integer") - .HasComment("变动数量,可为负值。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(如适用)。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Reason") - .HasColumnType("integer") - .HasComment("变动原因。"); - - b.Property("SourceId") - .HasColumnType("bigint") - .HasComment("来源 ID(订单、活动等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_point_ledgers", null, t => - { - t.HasComment("积分变动流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AvatarUrl") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像。"); - - b.Property("BirthDate") - .HasColumnType("timestamp with time zone") - .HasComment("生日。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GrowthValue") - .HasColumnType("integer") - .HasComment("成长值/经验值。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("注册时间。"); - - b.Property("MemberTierId") - .HasColumnType("bigint") - .HasComment("当前会员等级 ID。"); - - b.Property("Mobile") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("Nickname") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称。"); - - b.Property("PointsBalance") - .HasColumnType("integer") - .HasComment("会员积分余额。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会员状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Mobile") - .IsUnique(); - - b.ToTable("member_profiles", null, t => - { - t.HasComment("会员档案。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberTier", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BenefitsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("等级权益(JSON)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("等级名称。"); - - b.Property("RequiredGrowth") - .HasColumnType("integer") - .HasComment("所需成长值。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("member_tiers", null, t => - { - t.HasComment("会员等级定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.Merchant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("ApprovedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核通过时间。"); - - b.Property("ApprovedBy") - .HasColumnType("bigint") - .HasComment("审核通过人。"); - - b.Property("BrandAlias") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("品牌简称或别名。"); - - b.Property("BrandName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("品牌名称(对外展示)。"); - - b.Property("BusinessLicenseImageUrl") - .HasColumnType("text") - .HasComment("营业执照扫描件地址。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照号。"); - - b.Property("Category") - .HasColumnType("text") - .HasComment("品牌所属品类,如火锅、咖啡等。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("ClaimExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("领取过期时间。"); - - b.Property("ClaimedAt") - .HasColumnType("timestamp with time zone") - .HasComment("领取时间。"); - - b.Property("ClaimedBy") - .HasColumnType("bigint") - .HasComment("当前领取人。"); - - b.Property("ClaimedByName") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasComment("当前领取人姓名。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("联系邮箱。"); - - b.Property("ContactPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在区县。"); - - b.Property("FrozenAt") - .HasColumnType("timestamp with time zone") - .HasComment("冻结时间。"); - - b.Property("FrozenReason") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("冻结原因。"); - - b.Property("IsFrozen") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false) - .HasComment("是否冻结业务。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("入驻时间。"); - - b.Property("LastReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次审核时间。"); - - b.Property("LastReviewedBy") - .HasColumnType("bigint") - .HasComment("最近一次审核人。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度信息。"); - - b.Property("LegalPerson") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人或负责人姓名。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("品牌 Logo。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度信息。"); - - b.Property("OperatingMode") - .HasColumnType("integer") - .HasComment("经营模式(同一主体/不同主体)。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注或驳回原因。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制版本。"); - - b.Property("ServicePhone") - .HasColumnType("text") - .HasComment("客服电话。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("入驻状态。"); - - b.Property("SupportEmail") - .HasColumnType("text") - .HasComment("客服邮箱。"); - - b.Property("TaxNumber") - .HasColumnType("text") - .HasComment("税号/统一社会信用代码。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("ClaimedBy"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Status"); - - b.ToTable("merchants", null, t => - { - t.HasComment("商户主体信息,承载入驻和资质审核结果。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("显示顺序,越小越靠前。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否可用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("类目名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("merchant_categories", null, t => - { - t.HasComment("商户可选类目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantContract", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ContractNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("合同编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同结束时间。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("合同文件存储地址。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("SignedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签署时间。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("合同状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TerminatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("终止时间。"); - - b.Property("TerminationReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("终止原因。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "ContractNumber") - .IsUnique(); - - b.ToTable("merchant_contracts", null, t => - { - t.HasComment("商户合同记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantDocument", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DocumentNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("证照编号。"); - - b.Property("DocumentType") - .HasColumnType("integer") - .HasComment("证照类型。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期日期。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("证照文件链接。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签发日期。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Remarks") - .HasColumnType("text") - .HasComment("审核备注或驳回原因。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("审核状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "DocumentType"); - - b.ToTable("merchant_documents", null, t => - { - t.HasComment("商户提交的资质或证照材料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantStaff", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Email") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("邮箱地址。"); - - b.Property("IdentityUserId") - .HasColumnType("bigint") - .HasComment("登录账号 ID(指向统一身份体系)。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("员工姓名。"); - - b.Property("PermissionsJson") - .HasColumnType("text") - .HasComment("自定义权限(JSON)。"); - - b.Property("Phone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("员工角色类型。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("员工状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("可选的关联门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "Phone"); - - b.ToTable("merchant_staff", null, t => - { - t.HasComment("商户员工账号,支持门店维度分配。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.MapLocation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Landmark") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("打车/导航落点描述。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("名称。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店 ID,可空表示独立 POI。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("map_locations", null, t => - { - t.HasComment("地图 POI 信息,用于门店定位和推荐。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.NavigationRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("来源通道(小程序、H5 等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("请求时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TargetApp") - .HasColumnType("integer") - .HasComment("跳转的地图应用。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId", "RequestedAt"); - - b.ToTable("navigation_requests", null, t => - { - t.HasComment("用户发起的导航请求日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("扩展 JSON(规格、加料选项等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品或 SKU 标识。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称快照。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("自定义备注(口味要求)。"); - - b.Property("ShoppingCartId") - .HasColumnType("bigint") - .HasComment("所属购物车标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价快照。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ShoppingCartId"); - - b.ToTable("cart_items", null, t => - { - t.HasComment("购物车条目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItemAddon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CartItemId") - .HasColumnType("bigint") - .HasComment("所属购物车条目。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("OptionId") - .HasColumnType("bigint") - .HasComment("选项 ID(可对应 ProductAddonOption)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("cart_item_addons", null, t => - { - t.HasComment("购物车条目的加料/附加项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CheckoutSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("SessionToken") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话 Token。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.Property("ValidationResultJson") - .IsRequired() - .HasColumnType("text") - .HasComment("校验结果明细 JSON。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionToken") - .IsUnique(); - - b.ToTable("checkout_sessions", null, t => - { - t.HasComment("结账会话,记录校验上下文。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.ShoppingCart", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryPreference") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("履约方式(堂食/自提/配送)缓存。"); - - b.Property("LastModifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次修改时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("购物车状态,包含正常/锁定。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableContext") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌码或场景标识(扫码点餐)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId") - .IsUnique(); - - b.ToTable("shopping_carts", null, t => - { - t.HasComment("用户购物车,按租户/门店隔离。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.Order", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("取消原因。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("下单渠道。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("顾客姓名。"); - - b.Property("CustomerPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("顾客手机号。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryType") - .HasColumnType("integer") - .HasComment("履约类型。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("优惠金额。"); - - b.Property("FinishedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("ItemsAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("商品总额。"); - - b.Property("OrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("订单号。"); - - b.Property("PaidAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付时间。"); - - b.Property("PayableAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额。"); - - b.Property("PaymentStatus") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("QueueNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队号(如有)。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationId") - .HasColumnType("bigint") - .HasComment("预约 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TableNo") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("就餐桌号。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "Status"); - - b.ToTable("orders", null, t => - { - t.HasComment("交易订单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("自定义属性 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("折扣金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品 ID。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("SkuName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("SKU/规格描述。"); - - b.Property("SubTotal") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("小计。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("单位。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("OrderId"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("order_items", null, t => - { - t.HasComment("订单明细。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderStatusHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注信息。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识(可为空表示系统)。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("变更后的状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId", "OccurredAt"); - - b.ToTable("order_status_histories", null, t => - { - t.HasComment("订单状态流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.RefundRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("申请金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("ProcessedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核完成时间。"); - - b.Property("Reason") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("申请原因。"); - - b.Property("RefundNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("退款单号。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("用户提交时间。"); - - b.Property("ReviewNotes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "RefundNo") - .IsUnique(); - - b.ToTable("refund_requests", null, t => - { - t.HasComment("售后/退款申请。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("支付金额。"); - - b.Property("ChannelTransactionId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方渠道单号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Method") - .HasColumnType("integer") - .HasComment("支付方式。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付完成时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始回调内容。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("错误/备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TradeNo") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("平台交易号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("payment_records", null, t => - { - t.HasComment("支付流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRefundRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("退款金额。"); - - b.Property("ChannelRefundId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("渠道退款流水号。"); - - b.Property("CompletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("渠道返回的原始数据 JSON。"); - - b.Property("PaymentRecordId") - .HasColumnType("bigint") - .HasComment("原支付记录标识。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("退款请求时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PaymentRecordId"); - - b.ToTable("payment_refund_records", null, t => - { - t.HasComment("支付渠道退款流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.Product", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CategoryId") - .HasColumnType("bigint") - .HasComment("所属分类。"); - - b.Property("CoverImage") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("主图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("商品描述。"); - - b.Property("EnableDelivery") - .HasColumnType("boolean") - .HasComment("支持配送。"); - - b.Property("EnableDineIn") - .HasColumnType("boolean") - .HasComment("支持堂食。"); - - b.Property("EnablePickup") - .HasColumnType("boolean") - .HasComment("支持自提。"); - - b.Property("GalleryImages") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Gallery 图片逗号分隔。"); - - b.Property("IsFeatured") - .HasColumnType("boolean") - .HasComment("是否热门推荐。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("最大每单限购。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("现价。"); - - b.Property("SpuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("商品编码。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("商品状态。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("库存数量(可选)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("Subtitle") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("副标题/卖点。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("售卖单位(份/杯等)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SpuCode") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("products", null, t => - { - t.HasComment("商品(SPU)信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("MaxSelect") - .HasColumnType("integer") - .HasComment("最大选择数量。"); - - b.Property("MinSelect") - .HasColumnType("integer") - .HasComment("最小选择数量。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "Name"); - - b.ToTable("product_addon_groups", null, t => - { - t.HasComment("加料/做法分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AddonGroupId") - .HasColumnType("bigint") - .HasComment("所属加料分组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选项。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("product_addon_options", null, t => - { - t.HasComment("加料选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称,例如“辣度”“份量”。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型(单选/多选)。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("显示排序。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店,可为空表示所有门店共享。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("product_attribute_groups", null, t => - { - t.HasComment("商品规格/属性分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributeGroupId") - .HasColumnType("bigint") - .HasComment("所属规格组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选中。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AttributeGroupId", "Name") - .IsUnique(); - - b.ToTable("product_attribute_options", null, t => - { - t.HasComment("商品规格选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("分类描述。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分类名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("product_categories", null, t => - { - t.HasComment("商品分类。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductMediaAsset", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Caption") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述或标题。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MediaType") - .HasColumnType("integer") - .HasComment("媒体类型。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品标识。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Url") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("媒资链接。"); - - b.HasKey("Id"); - - b.ToTable("product_media_assets", null, t => - { - t.HasComment("商品媒资素材。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductPricingRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("条件描述(JSON),如会员等级、渠道等。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效结束时间。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("特殊价格。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("RuleType") - .HasColumnType("integer") - .HasComment("策略类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StartTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效开始时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("WeekdaysJson") - .HasColumnType("text") - .HasComment("生效星期(JSON 数组)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "RuleType"); - - b.ToTable("product_pricing_rules", null, t => - { - t.HasComment("商品价格策略,支持会员价/时段价等。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductSku", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("规格属性 JSON(记录选项 ID)。"); - - b.Property("Barcode") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("条形码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("售价。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SkuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("SKU 编码。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("可售库存。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weight") - .HasPrecision(10, 3) - .HasColumnType("numeric(10,3)") - .HasComment("重量(千克)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SkuCode") - .IsUnique(); - - b.ToTable("product_skus", null, t => - { - t.HasComment("商品 SKU,记录具体规格组合价格。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Queues.Entities.QueueTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CalledAt") - .HasColumnType("timestamp with time zone") - .HasComment("叫号时间。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedWaitMinutes") - .HasColumnType("integer") - .HasComment("预计等待分钟。"); - - b.Property("ExpiredAt") - .HasColumnType("timestamp with time zone") - .HasComment("过号时间。"); - - b.Property("PartySize") - .HasColumnType("integer") - .HasComment("就餐人数。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("获取或设置所属门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNumber") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.HasIndex("TenantId", "StoreId", "TicketNumber") - .IsUnique(); - - b.ToTable("queue_tickets", null, t => - { - t.HasComment("排队叫号。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Reservations.Entities.Reservation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CheckInCode") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("核销码/到店码。"); - - b.Property("CheckedInAt") - .HasColumnType("timestamp with time zone") - .HasComment("实际签到时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("客户姓名。"); - - b.Property("CustomerPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PeopleCount") - .HasColumnType("integer") - .HasComment("用餐人数。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("预约号。"); - - b.Property("ReservationTime") - .HasColumnType("timestamp with time zone") - .HasComment("预约时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TablePreference") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌型/标签。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ReservationNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("reservations", null, t => - { - t.HasComment("预约/预订记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.Store", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ActivatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核通过时间。"); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("Announcement") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("门店公告。"); - - b.Property("AuditStatus") - .HasColumnType("integer") - .HasComment("审核状态。"); - - b.Property("BusinessHours") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("门店营业时段描述(备用字符串)。"); - - b.Property("BusinessLicenseImageUrl") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("门店营业执照图片地址(主体不一致模式使用)。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(50) - .HasColumnType("character varying(50)") - .HasComment("门店营业执照号(主体不一致模式使用)。"); - - b.Property("BusinessStatus") - .HasColumnType("integer") - .HasComment("经营状态。"); - - b.Property("CategoryId") - .HasColumnType("bigint") - .HasComment("行业类目 ID。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("ClosureReason") - .HasColumnType("integer") - .HasComment("歇业原因。"); - - b.Property("ClosureReasonText") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("歇业原因补充说明。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("门店编码,便于扫码及外部对接。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家或地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("门店海报。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryRadiusKm") - .HasPrecision(6, 2) - .HasColumnType("numeric(6,2)") - .HasComment("默认配送半径(公里)。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("门店描述或公告。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区县信息。"); - - b.Property("ForceCloseReason") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("强制关闭原因。"); - - b.Property("ForceClosedAt") - .HasColumnType("timestamp with time zone") - .HasComment("强制关闭时间。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("LegalRepresentative") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasComment("门店法人(主体不一致模式使用)。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("高德/腾讯地图经度。"); - - b.Property("ManagerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("门店负责人姓名。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("门店名称。"); - - b.Property("OwnershipType") - .HasColumnType("integer") - .HasComment("主体类型。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("RegisteredAddress") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("门店注册地址(主体不一致模式使用)。"); - - b.Property("RejectionReason") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("审核驳回原因。"); - - b.Property("SignboardImageUrl") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("门头招牌图 URL。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("门店当前运营状态。"); - - b.Property("SubmittedAt") - .HasColumnType("timestamp with time zone") - .HasComment("提交审核时间。"); - - b.Property("SupportsDelivery") - .HasColumnType("boolean") - .HasComment("是否支持配送。"); - - b.Property("SupportsDineIn") - .HasColumnType("boolean") - .HasComment("是否支持堂食。"); - - b.Property("SupportsPickup") - .HasColumnType("boolean") - .HasComment("是否支持自提。"); - - b.Property("SupportsQueueing") - .HasColumnType("boolean") - .HasComment("支持排队叫号。"); - - b.Property("SupportsReservation") - .HasColumnType("boolean") - .HasComment("支持预约。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("门店标签(逗号分隔)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("Longitude", "Latitude") - .HasFilter("\"Longitude\" IS NOT NULL AND \"Latitude\" IS NOT NULL"); - - b.HasIndex("MerchantId", "BusinessLicenseNumber") - .IsUnique() - .HasFilter("\"BusinessLicenseNumber\" IS NOT NULL AND \"Status\" <> 3"); - - b.HasIndex("TenantId", "AuditStatus"); - - b.HasIndex("TenantId", "BusinessStatus"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.HasIndex("TenantId", "MerchantId"); - - b.HasIndex("TenantId", "OwnershipType"); - - b.ToTable("stores", null, t => - { - t.HasComment("门店信息,承载营业配置与能力。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreAuditRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("操作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("NewStatus") - .HasColumnType("integer") - .HasComment("操作后状态。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasComment("操作人名称。"); - - b.Property("PreviousStatus") - .HasColumnType("integer") - .HasComment("操作前状态。"); - - b.Property("RejectionReason") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("驳回理由文本。"); - - b.Property("RejectionReasonId") - .HasColumnType("bigint") - .HasComment("驳回理由 ID。"); - - b.Property("Remarks") - .HasMaxLength(1000) - .HasColumnType("character varying(1000)") - .HasComment("备注。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("CreatedAt"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("store_audit_records", null, t => - { - t.HasComment("门店审核记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreBusinessHour", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CapacityLimit") - .HasColumnType("integer") - .HasComment("最大接待容量或单量限制。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DayOfWeek") - .HasColumnType("integer") - .HasComment("星期几,0 表示周日。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间(本地时间)。"); - - b.Property("HourType") - .HasColumnType("integer") - .HasComment("时段类型(正常营业、休息、预约等)。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间(本地时间)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "DayOfWeek"); - - b.ToTable("store_business_hours", null, t => - { - t.HasComment("门店营业时段配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreDeliveryZone", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("EstimatedMinutes") - .HasColumnType("integer") - .HasComment("预计送达分钟。"); - - b.Property("MinimumOrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("起送价。"); - - b.Property("PolygonGeoJson") - .IsRequired() - .HasColumnType("text") - .HasComment("GeoJSON 表示的多边形范围。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ZoneName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ZoneName"); - - b.ToTable("store_delivery_zones", null, t => - { - t.HasComment("门店配送范围配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreEmployeeShift", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("排班角色。"); - - b.Property("ShiftDate") - .HasColumnType("timestamp with time zone") - .HasComment("班次日期。"); - - b.Property("StaffId") - .HasColumnType("bigint") - .HasComment("员工标识。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ShiftDate", "StaffId") - .IsUnique(); - - b.ToTable("store_employee_shifts", null, t => - { - t.HasComment("门店员工排班记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreFee", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BaseDeliveryFee") - .HasPrecision(10, 2) - .HasColumnType("numeric(10,2)") - .HasComment("基础配送费(元)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("FixedPackagingFee") - .HasPrecision(10, 2) - .HasColumnType("numeric(10,2)") - .HasComment("固定打包费(总计模式有效)。"); - - b.Property("FreeDeliveryThreshold") - .HasPrecision(10, 2) - .HasColumnType("numeric(10,2)") - .HasComment("免配送费门槛。"); - - b.Property("MinimumOrderAmount") - .HasPrecision(10, 2) - .HasColumnType("numeric(10,2)") - .HasComment("起送费(元)。"); - - b.Property("PackagingFeeMode") - .HasColumnType("integer") - .HasComment("打包费模式。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "StoreId") - .IsUnique(); - - b.ToTable("store_fees", null, t => - { - t.HasComment("门店费用配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreHoliday", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Date") - .HasColumnType("timestamp with time zone") - .HasComment("日期。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsClosed") - .HasColumnType("boolean") - .HasComment("是否全天闭店。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("说明内容。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Date") - .IsUnique(); - - b.ToTable("store_holidays", null, t => - { - t.HasComment("门店休息日或特殊营业日。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSetting", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowDaysAhead") - .HasColumnType("integer") - .HasComment("可预约天数(含当天)。"); - - b.Property("AllowToday") - .HasColumnType("boolean") - .HasComment("是否允许当天自提。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultCutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("默认截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单笔自提最大份数。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId") - .IsUnique(); - - b.ToTable("store_pickup_settings", null, t => - { - t.HasComment("门店自提配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSlot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("容量(份数)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("当天结束时间(UTC)。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("档期名称。"); - - b.Property("ReservedCount") - .HasColumnType("integer") - .HasComment("已占用数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("当天开始时间(UTC)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weekdays") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("适用星期(逗号分隔 1-7)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("store_pickup_slots", null, t => - { - t.HasComment("门店自提档期。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreQualification", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DocumentNumber") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasComment("证照编号。"); - - b.Property("ExpiresAt") - .HasColumnType("date") - .HasComment("到期日期。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("证照文件 URL。"); - - b.Property("IssuedAt") - .HasColumnType("date") - .HasComment("签发日期。"); - - b.Property("QualificationType") - .HasColumnType("integer") - .HasComment("资质类型。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(100) - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("ExpiresAt") - .HasFilter("\"ExpiresAt\" IS NOT NULL"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("store_qualifications", null, t => - { - t.HasComment("门店资质证照。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTable", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AreaId") - .HasColumnType("bigint") - .HasComment("所在区域 ID。"); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("可容纳人数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("QrCodeUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("桌码二维码地址。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前桌台状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("桌码。"); - - b.Property("Tags") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("桌台标签(堂食、快餐等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "TableCode") - .IsUnique(); - - b.ToTable("store_tables", null, t => - { - t.HasComment("桌台信息与二维码绑定。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTableArea", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("区域描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name") - .IsUnique(); - - b.ToTable("store_table_areas", null, t => - { - t.HasComment("门店桌台区域配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.QuotaPackage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("描述。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否上架。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("配额包名称。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("价格。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型。"); - - b.Property("QuotaValue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配额数值。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("排序。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("QuotaType", "IsActive", "SortOrder"); - - b.ToTable("quota_packages", null, t => - { - t.HasComment("配额包定义(平台提供的可购买配额包)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.Tenant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("text") - .HasComment("详细地址信息。"); - - b.Property("City") - .HasColumnType("text") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("租户短编码,作为跨系统引用的唯一标识。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("主联系人邮箱。"); - - b.Property("ContactName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("主联系人姓名。"); - - b.Property("ContactPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("主联系人电话。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家/地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("品牌海报或封面图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("服务生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("服务到期时间(UTC)。"); - - b.Property("Industry") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所属行业,如餐饮、零售等。"); - - b.Property("LegalEntityName") - .HasColumnType("text") - .HasComment("法人或公司主体名称。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("LOGO 图片地址。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("租户全称或品牌名称。"); - - b.Property("OperatingMode") - .HasColumnType("integer") - .HasComment("经营模式(同一主体/不同主体)。"); - - b.Property("PrimaryOwnerUserId") - .HasColumnType("bigint") - .HasComment("系统内对应的租户所有者账号 ID。"); - - b.Property("Province") - .HasColumnType("text") - .HasComment("所在省份或州。"); - - b.Property("Remarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息,用于运营记录特殊说明。"); - - b.Property("ShortName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("对外展示的简称。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("租户当前状态,涵盖审核、启用、停用等场景。"); - - b.Property("SuspendedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次暂停服务时间。"); - - b.Property("SuspensionReason") - .HasColumnType("text") - .HasComment("暂停或终止的原因说明。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("业务标签集合(逗号分隔)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Website") - .HasColumnType("text") - .HasComment("官网或主要宣传链接。"); - - b.HasKey("Id"); - - b.HasIndex("Code") - .IsUnique(); - - b.HasIndex("ContactPhone") - .IsUnique(); - - b.ToTable("tenants", null, t => - { - t.HasComment("平台租户信息,描述租户的生命周期与基础资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementType") - .HasColumnType("integer") - .HasComment("公告类型。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("公告正文(可为 Markdown/HTML,前端自行渲染)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("失效时间(UTC),为空表示长期有效。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否启用(已弃用,迁移期保留)。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("展示优先级,数值越大越靠前。"); - - b.Property("PublishedAt") - .HasColumnType("timestamp with time zone") - .HasComment("实际发布时间(UTC)。"); - - b.Property("PublisherScope") - .HasColumnType("integer") - .HasComment("发布者范围。"); - - b.Property("PublisherUserId") - .HasColumnType("bigint") - .HasComment("发布者用户 ID(平台或租户后台账号)。"); - - b.Property("RevokedAt") - .HasColumnType("timestamp with time zone") - .HasComment("撤销时间(UTC)。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("ScheduledPublishAt") - .HasColumnType("timestamp with time zone") - .HasComment("预定发布时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("公告状态。"); - - b.Property("TargetParameters") - .HasColumnType("text") - .HasComment("目标受众参数(JSON)。"); - - b.Property("TargetType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("目标受众类型。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("公告标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("Status", "EffectiveFrom") - .HasFilter("\"TenantId\" = 0"); - - b.HasIndex("TenantId", "AnnouncementType", "IsActive"); - - b.HasIndex("TenantId", "EffectiveFrom", "EffectiveTo"); - - b.HasIndex("TenantId", "Status", "EffectiveFrom"); - - b.ToTable("tenant_announcements", null, t => - { - t.HasComment("租户公告。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncementRead", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementId") - .HasColumnType("bigint") - .HasComment("公告 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("已读时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("已读用户 ID(后台账号),为空表示租户级已读。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AnnouncementId", "UserId") - .IsUnique(); - - b.ToTable("tenant_announcement_reads", null, t => - { - t.HasComment("租户公告已读记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantBillingStatement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AmountDue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额(原始金额)。"); - - b.Property("AmountPaid") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("BillingType") - .HasColumnType("integer") - .HasComment("账单类型(订阅账单/配额包账单/手动账单/续费账单)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Currency") - .IsRequired() - .ValueGeneratedOnAdd() - .HasMaxLength(8) - .HasColumnType("character varying(8)") - .HasDefaultValue("CNY") - .HasComment("货币类型(默认 CNY)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("折扣金额。"); - - b.Property("DueDate") - .HasColumnType("timestamp with time zone") - .HasComment("到期日。"); - - b.Property("LineItemsJson") - .HasColumnType("text") - .HasComment("账单明细 JSON,记录各项费用。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息(如:人工备注、取消原因等)。"); - - b.Property("OverdueNotifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("逾期通知时间。"); - - b.Property("PeriodEnd") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期结束时间。"); - - b.Property("PeriodStart") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期开始时间。"); - - b.Property("ReminderSentAt") - .HasColumnType("timestamp with time zone") - .HasComment("提醒发送时间(续费提醒、逾期提醒等)。"); - - b.Property("StatementNo") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("账单编号,供对账查询。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前付款状态。"); - - b.Property("SubscriptionId") - .HasColumnType("bigint") - .HasComment("关联的订阅 ID(仅当 BillingType 为 Subscription 或 Renewal 时有值)。"); - - b.Property("TaxAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("税费金额。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("CreatedAt") - .HasDatabaseName("idx_billing_created_at"); - - b.HasIndex("Status", "DueDate") - .HasDatabaseName("idx_billing_status_duedate") - .HasFilter("\"Status\" IN (0, 2)"); - - b.HasIndex("TenantId", "StatementNo") - .IsUnique(); - - b.HasIndex("TenantId", "Status", "DueDate") - .HasDatabaseName("idx_billing_tenant_status_duedate"); - - b.ToTable("tenant_billing_statements", null, t => - { - t.HasComment("租户账单,用于呈现周期性收费。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantNotification", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("发布通道(站内、邮件、短信等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("通知正文。"); - - b.Property("MetadataJson") - .HasColumnType("text") - .HasComment("附加元数据 JSON。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("租户是否已阅读。"); - - b.Property("SentAt") - .HasColumnType("timestamp with time zone") - .HasComment("推送时间。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("通知重要级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("通知标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Channel", "SentAt"); - - b.ToTable("tenant_notifications", null, t => - { - t.HasComment("面向租户的站内通知或消息推送。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantPackage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("套餐描述,包含适用场景、权益等。"); - - b.Property("FeaturePoliciesJson") - .HasColumnType("text") - .HasComment("权益明细 JSON,记录自定义特性开关。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否仍启用(平台控制)。"); - - b.Property("IsAllowNewTenantPurchase") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否允许新租户购买/选择(仅影响新购)。"); - - b.Property("IsPublicVisible") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否对外可见(展示页/套餐列表可见性)。"); - - b.Property("IsRecommended") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false) - .HasComment("是否推荐展示(运营推荐标识)。"); - - b.Property("MaxAccountCount") - .HasColumnType("integer") - .HasComment("允许创建的最大账号数。"); - - b.Property("MaxDeliveryOrders") - .HasColumnType("integer") - .HasComment("每月可调用的配送单数量上限。"); - - b.Property("MaxSmsCredits") - .HasColumnType("integer") - .HasComment("每月短信额度上限。"); - - b.Property("MaxStorageGb") - .HasColumnType("integer") - .HasComment("存储容量上限(GB)。"); - - b.Property("MaxStoreCount") - .HasColumnType("integer") - .HasComment("允许的最大门店数。"); - - b.Property("MonthlyPrice") - .HasColumnType("numeric") - .HasComment("月付价格,单位:人民币元。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("套餐名称,展示给租户的简称。"); - - b.Property("PackageType") - .HasColumnType("integer") - .HasComment("套餐分类(试用、标准、旗舰等)。"); - - b.Property("PublishStatus") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("发布状态:0=草稿,1=已发布。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("展示排序,数值越小越靠前。"); - - b.PrimitiveCollection("Tags") - .IsRequired() - .HasColumnType("text[]") - .HasComment("套餐标签(用于展示与对比页)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("YearlyPrice") - .HasColumnType("numeric") - .HasComment("年付价格,单位:人民币元。"); - - b.HasKey("Id"); - - b.HasIndex("IsActive", "SortOrder"); - - b.HasIndex("PublishStatus", "IsActive", "IsPublicVisible", "IsAllowNewTenantPurchase", "SortOrder"); - - b.ToTable("tenant_packages", null, t => - { - t.HasComment("平台提供的租户套餐定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantPayment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("支付金额。"); - - b.Property("BillingStatementId") - .HasColumnType("bigint") - .HasComment("关联的账单 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Method") - .HasColumnType("integer") - .HasComment("支付方式。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付时间。"); - - b.Property("ProofUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("支付凭证 URL。"); - - b.Property("RefundReason") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("退款原因。"); - - b.Property("RefundedAt") - .HasColumnType("timestamp with time zone") - .HasComment("退款时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TransactionNo") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("交易号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("VerifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核时间。"); - - b.Property("VerifiedBy") - .HasColumnType("bigint") - .HasComment("审核人 ID(管理员)。"); - - b.HasKey("Id"); - - b.HasIndex("TransactionNo") - .HasDatabaseName("idx_payment_transaction_no") - .HasFilter("\"TransactionNo\" IS NOT NULL"); - - b.HasIndex("BillingStatementId", "PaidAt") - .HasDatabaseName("idx_payment_billing_paidat"); - - b.HasIndex("TenantId", "BillingStatementId"); - - b.ToTable("tenant_payments", null, t => - { - t.HasComment("租户支付记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaPackagePurchase", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiredAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(可选)。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("购买价格。"); - - b.Property("PurchasedAt") - .HasColumnType("timestamp with time zone") - .HasComment("购买时间。"); - - b.Property("QuotaPackageId") - .HasColumnType("bigint") - .HasComment("配额包 ID。"); - - b.Property("QuotaValue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("购买时的配额值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "QuotaPackageId", "PurchasedAt"); - - b.ToTable("tenant_quota_package_purchases", null, t => - { - t.HasComment("租户配额包购买记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaUsage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LastResetAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次重置时间。"); - - b.Property("LimitValue") - .HasColumnType("numeric") - .HasComment("当前配额上限。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型,例如门店数、短信条数等。"); - - b.Property("ResetCycle") - .HasColumnType("text") - .HasComment("配额刷新周期描述(如月、年)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedValue") - .HasColumnType("numeric") - .HasComment("已消耗的数量。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "QuotaType") - .IsUnique(); - - b.ToTable("tenant_quota_usages", null, t => - { - t.HasComment("租户配额使用情况快照。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaUsageHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChangeAmount") - .HasColumnType("numeric") - .HasComment("变更量(可选)。"); - - b.Property("ChangeReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("变更原因(可选)。"); - - b.Property("ChangeType") - .HasColumnType("integer") - .HasComment("变更类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LimitValue") - .HasColumnType("numeric") - .HasComment("限额值(记录时刻的快照)。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型。"); - - b.Property("RecordedAt") - .HasColumnType("timestamp with time zone") - .HasComment("记录时间(UTC)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedValue") - .HasColumnType("numeric") - .HasComment("已使用值(记录时刻的快照)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "RecordedAt"); - - b.HasIndex("TenantId", "QuotaType", "RecordedAt"); - - b.ToTable("tenant_quota_usage_histories", null, t => - { - t.HasComment("租户配额使用历史记录(用于追踪配额上下限与使用量的时间序列变化)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantReviewClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ClaimedAt") - .HasColumnType("timestamp with time zone") - .HasComment("领取时间(UTC)。"); - - b.Property("ClaimedBy") - .HasColumnType("bigint") - .HasComment("领取人用户 ID。"); - - b.Property("ClaimedByName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("领取人名称(展示用快照)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReleasedAt") - .HasColumnType("timestamp with time zone") - .HasComment("释放时间(UTC),未释放时为 null。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("被领取的租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("ClaimedBy"); - - b.HasIndex("TenantId") - .IsUnique() - .HasFilter("\"ReleasedAt\" IS NULL AND \"DeletedAt\" IS NULL"); - - b.ToTable("tenant_review_claims", null, t => - { - t.HasComment("租户入驻审核领取记录(防止多管理员并发审核)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscription", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AutoRenew") - .HasColumnType("boolean") - .HasComment("是否开启自动续费。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("订阅生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("订阅到期时间(UTC)。"); - - b.Property("NextBillingDate") - .HasColumnType("timestamp with time zone") - .HasComment("下一个计费时间,配合自动续费使用。"); - - b.Property("Notes") - .HasColumnType("text") - .HasComment("运营备注信息。"); - - b.Property("ScheduledPackageId") - .HasColumnType("bigint") - .HasComment("若已排期升降配,对应的新套餐 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("订阅当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TenantPackageId") - .HasColumnType("bigint") - .HasComment("当前订阅关联的套餐标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantPackageId"); - - b.ToTable("tenant_subscriptions", null, t => - { - t.HasComment("租户套餐订阅记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscriptionHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasColumnType("numeric") - .HasComment("相关费用。"); - - b.Property("ChangeType") - .HasColumnType("integer") - .HasComment("变更类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Currency") - .HasMaxLength(8) - .HasColumnType("character varying(8)") - .HasComment("币种。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("FromPackageId") - .HasColumnType("bigint") - .HasComment("原套餐 ID。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("租户标识。"); - - b.Property("TenantSubscriptionId") - .HasColumnType("bigint") - .HasComment("对应的订阅 ID。"); - - b.Property("ToPackageId") - .HasColumnType("bigint") - .HasComment("新套餐 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantSubscriptionId"); - - b.ToTable("tenant_subscription_histories", null, t => - { - t.HasComment("租户套餐订阅变更记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantVerificationProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdditionalDataJson") - .HasColumnType("text") - .HasComment("附加资料(JSON)。"); - - b.Property("BankAccountName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("开户名。"); - - b.Property("BankAccountNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("银行账号。"); - - b.Property("BankName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("银行名称。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照编号。"); - - b.Property("BusinessLicenseUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营业执照文件地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LegalPersonIdBackUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证反面。"); - - b.Property("LegalPersonIdFrontUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证正面。"); - - b.Property("LegalPersonIdNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("法人身份证号。"); - - b.Property("LegalPersonName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人姓名。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注。"); - - b.Property("ReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核时间。"); - - b.Property("ReviewedBy") - .HasColumnType("bigint") - .HasComment("审核人 ID。"); - - b.Property("ReviewedByName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("审核人姓名。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("实名状态。"); - - b.Property("SubmittedAt") - .HasColumnType("timestamp with time zone") - .HasComment("提交时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("对应的租户标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId") - .IsUnique(); - - b.ToTable("tenant_verification_profiles", null, t => - { - t.HasComment("租户实名认证资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.HasOne("TakeoutSaaS.Domain.Orders.Entities.Order", null) - .WithMany() - .HasForeignKey("OrderId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20260120045054_ChangeStoreQualificationDateColumns.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20260120045054_ChangeStoreQualificationDateColumns.cs deleted file mode 100644 index be216f0..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20260120045054_ChangeStoreQualificationDateColumns.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - /// - public partial class ChangeStoreQualificationDateColumns : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "IssuedAt", - table: "store_qualifications", - type: "date", - nullable: true, - comment: "签发日期。", - oldClrType: typeof(DateTime), - oldType: "timestamp with time zone", - oldNullable: true, - oldComment: "签发日期。"); - - migrationBuilder.AlterColumn( - name: "ExpiresAt", - table: "store_qualifications", - type: "date", - nullable: true, - comment: "到期日期。", - oldClrType: typeof(DateTime), - oldType: "timestamp with time zone", - oldNullable: true, - oldComment: "到期日期。"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "IssuedAt", - table: "store_qualifications", - type: "timestamp with time zone", - nullable: true, - comment: "签发日期。", - oldClrType: typeof(DateOnly), - oldType: "date", - oldNullable: true, - oldComment: "签发日期。"); - - migrationBuilder.AlterColumn( - name: "ExpiresAt", - table: "store_qualifications", - type: "timestamp with time zone", - nullable: true, - comment: "到期日期。", - oldClrType: typeof(DateOnly), - oldType: "date", - oldNullable: true, - oldComment: "到期日期。"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20260120045217_UpdateStoreQualificationDateFields.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20260120045217_UpdateStoreQualificationDateFields.Designer.cs deleted file mode 100644 index 567ecd5..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20260120045217_UpdateStoreQualificationDateFields.Designer.cs +++ /dev/null @@ -1,7391 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.App.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - [DbContext(typeof(TakeoutAppDbContext))] - [Migration("20260120045217_UpdateStoreQualificationDateFields")] - partial class UpdateStoreQualificationDateFields - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.1") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricAlertRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionJson") - .IsRequired() - .HasColumnType("text") - .HasComment("触发条件 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Enabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("关联指标。"); - - b.Property("NotificationChannels") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("通知渠道。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("告警级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "Severity"); - - b.ToTable("metric_alert_rules", null, t => - { - t.HasComment("指标告警规则。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricDefinition", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("指标编码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultAggregation") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("默认聚合方式。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("说明。"); - - b.Property("DimensionsJson") - .HasColumnType("text") - .HasComment("维度描述 JSON。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("指标名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("metric_definitions", null, t => - { - t.HasComment("指标定义,描述可观测的数据点。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricSnapshot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DimensionKey") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("维度键(JSON)。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("指标定义 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Value") - .HasPrecision(18, 4) - .HasColumnType("numeric(18,4)") - .HasComment("数值。"); - - b.Property("WindowEnd") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口结束。"); - - b.Property("WindowStart") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口开始。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "DimensionKey", "WindowStart", "WindowEnd") - .IsUnique(); - - b.ToTable("metric_snapshots", null, t => - { - t.HasComment("指标快照,用于大盘展示。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.Coupon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("券码或序列号。"); - - b.Property("CouponTemplateId") - .HasColumnType("bigint") - .HasComment("模板标识。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("发放时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID(已使用时记录)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedAt") - .HasColumnType("timestamp with time zone") - .HasComment("使用时间。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("归属用户。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("coupons", null, t => - { - t.HasComment("用户领取的券。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.CouponTemplate", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowStack") - .HasColumnType("boolean") - .HasComment("是否允许叠加其他优惠。"); - - b.Property("ChannelsJson") - .HasColumnType("text") - .HasComment("发放渠道(JSON)。"); - - b.Property("ClaimedQuantity") - .HasColumnType("integer") - .HasComment("已领取数量。"); - - b.Property("CouponType") - .HasColumnType("integer") - .HasComment("券类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("DiscountCap") - .HasColumnType("numeric") - .HasComment("折扣上限(针对折扣券)。"); - - b.Property("MinimumSpend") - .HasColumnType("numeric") - .HasComment("最低消费门槛。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("模板名称。"); - - b.Property("ProductScopeJson") - .HasColumnType("text") - .HasComment("适用品类或商品范围(JSON)。"); - - b.Property("RelativeValidDays") - .HasColumnType("integer") - .HasComment("有效天数(相对发放时间)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreScopeJson") - .HasColumnType("text") - .HasComment("适用门店 ID 集合(JSON)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TotalQuantity") - .HasColumnType("integer") - .HasComment("总发放数量上限。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ValidFrom") - .HasColumnType("timestamp with time zone") - .HasComment("可用开始时间。"); - - b.Property("ValidTo") - .HasColumnType("timestamp with time zone") - .HasComment("可用结束时间。"); - - b.Property("Value") - .HasColumnType("numeric") - .HasComment("面值或折扣额度。"); - - b.HasKey("Id"); - - b.ToTable("coupon_templates", null, t => - { - t.HasComment("优惠券模板。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.PromotionCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AudienceDescription") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("目标人群描述。"); - - b.Property("BannerUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营销素材(如 banner)。"); - - b.Property("Budget") - .HasColumnType("numeric") - .HasComment("预算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("PromotionType") - .HasColumnType("integer") - .HasComment("活动类型。"); - - b.Property("RulesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("活动规则 JSON。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("活动状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("promotion_campaigns", null, t => - { - t.HasComment("营销活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChatSessionId") - .HasColumnType("bigint") - .HasComment("会话标识。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("消息内容。"); - - b.Property("ContentType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("消息类型(文字/图片/语音等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRead") - .HasColumnType("boolean") - .HasComment("是否已读。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("读取时间。"); - - b.Property("SenderType") - .HasColumnType("integer") - .HasComment("发送方类型。"); - - b.Property("SenderUserId") - .HasColumnType("bigint") - .HasComment("发送方用户 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ChatSessionId", "CreatedAt"); - - b.ToTable("chat_messages", null, t => - { - t.HasComment("会话消息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AgentUserId") - .HasColumnType("bigint") - .HasComment("当前客服员工 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("顾客用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndedAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("IsBotActive") - .HasColumnType("boolean") - .HasComment("是否机器人接待中。"); - - b.Property("SessionCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话编号。"); - - b.Property("StartedAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店(可空为平台)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionCode") - .IsUnique(); - - b.ToTable("chat_sessions", null, t => - { - t.HasComment("客服会话。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.SupportTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AssignedAgentId") - .HasColumnType("bigint") - .HasComment("指派的客服。"); - - b.Property("ClosedAt") - .HasColumnType("timestamp with time zone") - .HasComment("关闭时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("客户用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .IsRequired() - .HasColumnType("text") - .HasComment("工单详情。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单(如有)。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("优先级。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("Subject") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("工单主题。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("工单编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TicketNo") - .IsUnique(); - - b.ToTable("support_tickets", null, t => - { - t.HasComment("客服工单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.TicketComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttachmentsJson") - .HasColumnType("text") - .HasComment("附件 JSON。"); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人 ID。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsInternal") - .HasColumnType("boolean") - .HasComment("是否内部备注。"); - - b.Property("SupportTicketId") - .HasColumnType("bigint") - .HasComment("工单标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SupportTicketId"); - - b.ToTable("ticket_comments", null, t => - { - t.HasComment("工单评论/流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryEvent", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryOrderId") - .HasColumnType("bigint") - .HasComment("配送单标识。"); - - b.Property("EventType") - .HasColumnType("integer") - .HasComment("事件类型。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("事件描述。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始数据 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DeliveryOrderId", "EventType"); - - b.ToTable("delivery_events", null, t => - { - t.HasComment("配送状态事件流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CourierName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("骑手姓名。"); - - b.Property("CourierPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("骑手电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveredAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("DispatchedAt") - .HasColumnType("timestamp with time zone") - .HasComment("下发时间。"); - - b.Property("FailureReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("异常原因。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("获取或设置关联订单 ID。"); - - b.Property("PickedUpAt") - .HasColumnType("timestamp with time zone") - .HasComment("取餐时间。"); - - b.Property("Provider") - .HasColumnType("integer") - .HasComment("配送服务商。"); - - b.Property("ProviderOrderId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方配送单号。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId") - .IsUnique(); - - b.ToTable("delivery_orders", null, t => - { - t.HasComment("配送单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliateOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("推广人标识。"); - - b.Property("BuyerUserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedCommission") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("预计佣金。"); - - b.Property("OrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("订单金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("SettledAt") - .HasColumnType("timestamp with time zone") - .HasComment("结算完成时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "OrderId") - .IsUnique(); - - b.ToTable("affiliate_orders", null, t => - { - t.HasComment("分销订单记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePartner", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChannelType") - .HasColumnType("integer") - .HasComment("渠道类型。"); - - b.Property("CommissionRate") - .HasColumnType("numeric") - .HasComment("分成比例(0-1)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称或渠道名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID(如绑定平台账号)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DisplayName"); - - b.ToTable("affiliate_partners", null, t => - { - t.HasComment("分销/推广合作伙伴。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePayout", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("合作伙伴标识。"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("结算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("打款时间。"); - - b.Property("Period") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("结算周期描述。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "Period") - .IsUnique(); - - b.ToTable("affiliate_payouts", null, t => - { - t.HasComment("佣金结算记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowMakeupCount") - .HasColumnType("integer") - .HasComment("支持补签次数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("活动描述。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("结束日期。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("RewardsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("连签奖励 JSON。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("开始日期。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name"); - - b.ToTable("checkin_campaigns", null, t => - { - t.HasComment("签到活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CheckInCampaignId") - .HasColumnType("bigint") - .HasComment("活动标识。"); - - b.Property("CheckInDate") - .HasColumnType("timestamp with time zone") - .HasComment("签到日期(本地)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsMakeup") - .HasColumnType("boolean") - .HasComment("是否补签。"); - - b.Property("RewardJson") - .IsRequired() - .HasColumnType("text") - .HasComment("获得奖励 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "CheckInCampaignId", "UserId", "CheckInDate") - .IsUnique(); - - b.ToTable("checkin_records", null, t => - { - t.HasComment("用户签到记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsDeleted") - .HasColumnType("boolean") - .HasComment("状态。"); - - b.Property("ParentId") - .HasColumnType("bigint") - .HasComment("父级评论 ID。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "CreatedAt"); - - b.ToTable("community_comments", null, t => - { - t.HasComment("社区评论。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityPost", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("作者用户 ID。"); - - b.Property("CommentCount") - .HasColumnType("integer") - .HasComment("评论数。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LikeCount") - .HasColumnType("integer") - .HasComment("点赞数。"); - - b.Property("MediaJson") - .HasColumnType("text") - .HasComment("媒体资源 JSON。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AuthorUserId", "CreatedAt"); - - b.ToTable("community_posts", null, t => - { - t.HasComment("社区动态。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityReaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态 ID。"); - - b.Property("ReactedAt") - .HasColumnType("timestamp with time zone") - .HasComment("时间戳。"); - - b.Property("ReactionType") - .HasColumnType("integer") - .HasComment("反应类型。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "UserId") - .IsUnique(); - - b.ToTable("community_reactions", null, t => - { - t.HasComment("社区互动反馈。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentCount") - .HasColumnType("integer") - .HasComment("当前已参与人数。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("GroupOrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("拼单编号。"); - - b.Property("GroupPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("拼团价格。"); - - b.Property("LeaderUserId") - .HasColumnType("bigint") - .HasComment("团长用户 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("关联商品或套餐。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("拼团状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("SucceededAt") - .HasColumnType("timestamp with time zone") - .HasComment("成团时间。"); - - b.Property("TargetCount") - .HasColumnType("integer") - .HasComment("成团需要的人数。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderNo") - .IsUnique(); - - b.ToTable("group_orders", null, t => - { - t.HasComment("拼单活动。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupParticipant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GroupOrderId") - .HasColumnType("bigint") - .HasComment("拼单活动标识。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("参与时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("对应订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("参与状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderId", "UserId") - .IsUnique(); - - b.ToTable("group_participants", null, t => - { - t.HasComment("拼单参与者。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryAdjustment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdjustmentType") - .HasColumnType("integer") - .HasComment("调整类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("InventoryItemId") - .HasColumnType("bigint") - .HasComment("对应的库存记录标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("调整数量,正数增加,负数减少。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("原因说明。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "InventoryItemId", "OccurredAt"); - - b.ToTable("inventory_adjustments", null, t => - { - t.HasComment("库存调整记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryBatch", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("ProductionDate") - .HasColumnType("timestamp with time zone") - .HasComment("生产日期。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("入库数量。"); - - b.Property("RemainingQuantity") - .HasColumnType("integer") - .HasComment("剩余数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber") - .IsUnique(); - - b.ToTable("inventory_batches", null, t => - { - t.HasComment("SKU 批次信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchConsumeStrategy") - .HasColumnType("integer") - .HasComment("批次扣减策略。"); - - b.Property("BatchNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号,可为空表示混批。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售商品。"); - - b.Property("IsSoldOut") - .HasColumnType("boolean") - .HasComment("是否标记售罄。"); - - b.Property("Location") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("储位或仓位信息。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单品限购(覆盖商品级 MaxQuantityPerOrder)。"); - - b.Property("PresaleCapacity") - .HasColumnType("integer") - .HasComment("预售名额(上限)。"); - - b.Property("PresaleEndTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售结束时间(UTC)。"); - - b.Property("PresaleLocked") - .HasColumnType("integer") - .HasComment("当前预售已锁定数量。"); - - b.Property("PresaleStartTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售开始时间(UTC)。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("QuantityOnHand") - .HasColumnType("integer") - .HasComment("可用库存。"); - - b.Property("QuantityReserved") - .HasColumnType("integer") - .HasComment("已锁定库存(订单占用)。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("SafetyStock") - .HasColumnType("integer") - .HasComment("安全库存阈值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber"); - - b.ToTable("inventory_items", null, t => - { - t.HasComment("SKU 在门店的库存信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryLockRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("IdempotencyKey") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("幂等键。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售锁定。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU ID。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("锁定数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("锁定状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "IdempotencyKey") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "Status"); - - b.ToTable("inventory_lock_records", null, t => - { - t.HasComment("库存锁定记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberPointLedger", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BalanceAfterChange") - .HasColumnType("integer") - .HasComment("变动后余额。"); - - b.Property("ChangeAmount") - .HasColumnType("integer") - .HasComment("变动数量,可为负值。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(如适用)。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Reason") - .HasColumnType("integer") - .HasComment("变动原因。"); - - b.Property("SourceId") - .HasColumnType("bigint") - .HasComment("来源 ID(订单、活动等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_point_ledgers", null, t => - { - t.HasComment("积分变动流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AvatarUrl") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像。"); - - b.Property("BirthDate") - .HasColumnType("timestamp with time zone") - .HasComment("生日。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GrowthValue") - .HasColumnType("integer") - .HasComment("成长值/经验值。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("注册时间。"); - - b.Property("MemberTierId") - .HasColumnType("bigint") - .HasComment("当前会员等级 ID。"); - - b.Property("Mobile") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("Nickname") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称。"); - - b.Property("PointsBalance") - .HasColumnType("integer") - .HasComment("会员积分余额。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会员状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Mobile") - .IsUnique(); - - b.ToTable("member_profiles", null, t => - { - t.HasComment("会员档案。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberTier", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BenefitsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("等级权益(JSON)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("等级名称。"); - - b.Property("RequiredGrowth") - .HasColumnType("integer") - .HasComment("所需成长值。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("member_tiers", null, t => - { - t.HasComment("会员等级定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.Merchant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("ApprovedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核通过时间。"); - - b.Property("ApprovedBy") - .HasColumnType("bigint") - .HasComment("审核通过人。"); - - b.Property("BrandAlias") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("品牌简称或别名。"); - - b.Property("BrandName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("品牌名称(对外展示)。"); - - b.Property("BusinessLicenseImageUrl") - .HasColumnType("text") - .HasComment("营业执照扫描件地址。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照号。"); - - b.Property("Category") - .HasColumnType("text") - .HasComment("品牌所属品类,如火锅、咖啡等。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("ClaimExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("领取过期时间。"); - - b.Property("ClaimedAt") - .HasColumnType("timestamp with time zone") - .HasComment("领取时间。"); - - b.Property("ClaimedBy") - .HasColumnType("bigint") - .HasComment("当前领取人。"); - - b.Property("ClaimedByName") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasComment("当前领取人姓名。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("联系邮箱。"); - - b.Property("ContactPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在区县。"); - - b.Property("FrozenAt") - .HasColumnType("timestamp with time zone") - .HasComment("冻结时间。"); - - b.Property("FrozenReason") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("冻结原因。"); - - b.Property("IsFrozen") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false) - .HasComment("是否冻结业务。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("入驻时间。"); - - b.Property("LastReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次审核时间。"); - - b.Property("LastReviewedBy") - .HasColumnType("bigint") - .HasComment("最近一次审核人。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度信息。"); - - b.Property("LegalPerson") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人或负责人姓名。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("品牌 Logo。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度信息。"); - - b.Property("OperatingMode") - .HasColumnType("integer") - .HasComment("经营模式(同一主体/不同主体)。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注或驳回原因。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制版本。"); - - b.Property("ServicePhone") - .HasColumnType("text") - .HasComment("客服电话。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("入驻状态。"); - - b.Property("SupportEmail") - .HasColumnType("text") - .HasComment("客服邮箱。"); - - b.Property("TaxNumber") - .HasColumnType("text") - .HasComment("税号/统一社会信用代码。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("ClaimedBy"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Status"); - - b.ToTable("merchants", null, t => - { - t.HasComment("商户主体信息,承载入驻和资质审核结果。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("显示顺序,越小越靠前。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否可用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("类目名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("merchant_categories", null, t => - { - t.HasComment("商户可选类目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantContract", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ContractNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("合同编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同结束时间。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("合同文件存储地址。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("SignedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签署时间。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("合同状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TerminatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("终止时间。"); - - b.Property("TerminationReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("终止原因。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "ContractNumber") - .IsUnique(); - - b.ToTable("merchant_contracts", null, t => - { - t.HasComment("商户合同记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantDocument", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DocumentNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("证照编号。"); - - b.Property("DocumentType") - .HasColumnType("integer") - .HasComment("证照类型。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期日期。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("证照文件链接。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签发日期。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Remarks") - .HasColumnType("text") - .HasComment("审核备注或驳回原因。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("审核状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "DocumentType"); - - b.ToTable("merchant_documents", null, t => - { - t.HasComment("商户提交的资质或证照材料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantStaff", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Email") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("邮箱地址。"); - - b.Property("IdentityUserId") - .HasColumnType("bigint") - .HasComment("登录账号 ID(指向统一身份体系)。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("员工姓名。"); - - b.Property("PermissionsJson") - .HasColumnType("text") - .HasComment("自定义权限(JSON)。"); - - b.Property("Phone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("员工角色类型。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("员工状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("可选的关联门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "Phone"); - - b.ToTable("merchant_staff", null, t => - { - t.HasComment("商户员工账号,支持门店维度分配。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.MapLocation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Landmark") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("打车/导航落点描述。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("名称。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店 ID,可空表示独立 POI。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("map_locations", null, t => - { - t.HasComment("地图 POI 信息,用于门店定位和推荐。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.NavigationRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("来源通道(小程序、H5 等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("请求时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TargetApp") - .HasColumnType("integer") - .HasComment("跳转的地图应用。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId", "RequestedAt"); - - b.ToTable("navigation_requests", null, t => - { - t.HasComment("用户发起的导航请求日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("扩展 JSON(规格、加料选项等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品或 SKU 标识。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称快照。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("自定义备注(口味要求)。"); - - b.Property("ShoppingCartId") - .HasColumnType("bigint") - .HasComment("所属购物车标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价快照。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ShoppingCartId"); - - b.ToTable("cart_items", null, t => - { - t.HasComment("购物车条目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItemAddon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CartItemId") - .HasColumnType("bigint") - .HasComment("所属购物车条目。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("OptionId") - .HasColumnType("bigint") - .HasComment("选项 ID(可对应 ProductAddonOption)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("cart_item_addons", null, t => - { - t.HasComment("购物车条目的加料/附加项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CheckoutSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("SessionToken") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话 Token。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.Property("ValidationResultJson") - .IsRequired() - .HasColumnType("text") - .HasComment("校验结果明细 JSON。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionToken") - .IsUnique(); - - b.ToTable("checkout_sessions", null, t => - { - t.HasComment("结账会话,记录校验上下文。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.ShoppingCart", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryPreference") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("履约方式(堂食/自提/配送)缓存。"); - - b.Property("LastModifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次修改时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("购物车状态,包含正常/锁定。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableContext") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌码或场景标识(扫码点餐)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId") - .IsUnique(); - - b.ToTable("shopping_carts", null, t => - { - t.HasComment("用户购物车,按租户/门店隔离。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.Order", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("取消原因。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("下单渠道。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("顾客姓名。"); - - b.Property("CustomerPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("顾客手机号。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryType") - .HasColumnType("integer") - .HasComment("履约类型。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("优惠金额。"); - - b.Property("FinishedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("ItemsAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("商品总额。"); - - b.Property("OrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("订单号。"); - - b.Property("PaidAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付时间。"); - - b.Property("PayableAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额。"); - - b.Property("PaymentStatus") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("QueueNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队号(如有)。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationId") - .HasColumnType("bigint") - .HasComment("预约 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TableNo") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("就餐桌号。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "Status"); - - b.ToTable("orders", null, t => - { - t.HasComment("交易订单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("自定义属性 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("折扣金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品 ID。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("SkuName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("SKU/规格描述。"); - - b.Property("SubTotal") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("小计。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("单位。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("OrderId"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("order_items", null, t => - { - t.HasComment("订单明细。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderStatusHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注信息。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识(可为空表示系统)。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("变更后的状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId", "OccurredAt"); - - b.ToTable("order_status_histories", null, t => - { - t.HasComment("订单状态流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.RefundRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("申请金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("ProcessedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核完成时间。"); - - b.Property("Reason") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("申请原因。"); - - b.Property("RefundNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("退款单号。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("用户提交时间。"); - - b.Property("ReviewNotes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "RefundNo") - .IsUnique(); - - b.ToTable("refund_requests", null, t => - { - t.HasComment("售后/退款申请。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("支付金额。"); - - b.Property("ChannelTransactionId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方渠道单号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Method") - .HasColumnType("integer") - .HasComment("支付方式。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付完成时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始回调内容。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("错误/备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TradeNo") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("平台交易号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("payment_records", null, t => - { - t.HasComment("支付流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRefundRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("退款金额。"); - - b.Property("ChannelRefundId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("渠道退款流水号。"); - - b.Property("CompletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("渠道返回的原始数据 JSON。"); - - b.Property("PaymentRecordId") - .HasColumnType("bigint") - .HasComment("原支付记录标识。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("退款请求时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PaymentRecordId"); - - b.ToTable("payment_refund_records", null, t => - { - t.HasComment("支付渠道退款流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.Product", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CategoryId") - .HasColumnType("bigint") - .HasComment("所属分类。"); - - b.Property("CoverImage") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("主图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("商品描述。"); - - b.Property("EnableDelivery") - .HasColumnType("boolean") - .HasComment("支持配送。"); - - b.Property("EnableDineIn") - .HasColumnType("boolean") - .HasComment("支持堂食。"); - - b.Property("EnablePickup") - .HasColumnType("boolean") - .HasComment("支持自提。"); - - b.Property("GalleryImages") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Gallery 图片逗号分隔。"); - - b.Property("IsFeatured") - .HasColumnType("boolean") - .HasComment("是否热门推荐。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("最大每单限购。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("现价。"); - - b.Property("SpuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("商品编码。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("商品状态。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("库存数量(可选)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("Subtitle") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("副标题/卖点。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("售卖单位(份/杯等)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SpuCode") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("products", null, t => - { - t.HasComment("商品(SPU)信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("MaxSelect") - .HasColumnType("integer") - .HasComment("最大选择数量。"); - - b.Property("MinSelect") - .HasColumnType("integer") - .HasComment("最小选择数量。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "Name"); - - b.ToTable("product_addon_groups", null, t => - { - t.HasComment("加料/做法分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AddonGroupId") - .HasColumnType("bigint") - .HasComment("所属加料分组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选项。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("product_addon_options", null, t => - { - t.HasComment("加料选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称,例如“辣度”“份量”。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型(单选/多选)。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("显示排序。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店,可为空表示所有门店共享。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("product_attribute_groups", null, t => - { - t.HasComment("商品规格/属性分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributeGroupId") - .HasColumnType("bigint") - .HasComment("所属规格组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选中。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AttributeGroupId", "Name") - .IsUnique(); - - b.ToTable("product_attribute_options", null, t => - { - t.HasComment("商品规格选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("分类描述。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分类名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("product_categories", null, t => - { - t.HasComment("商品分类。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductMediaAsset", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Caption") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述或标题。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MediaType") - .HasColumnType("integer") - .HasComment("媒体类型。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品标识。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Url") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("媒资链接。"); - - b.HasKey("Id"); - - b.ToTable("product_media_assets", null, t => - { - t.HasComment("商品媒资素材。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductPricingRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("条件描述(JSON),如会员等级、渠道等。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效结束时间。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("特殊价格。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("RuleType") - .HasColumnType("integer") - .HasComment("策略类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StartTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效开始时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("WeekdaysJson") - .HasColumnType("text") - .HasComment("生效星期(JSON 数组)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "RuleType"); - - b.ToTable("product_pricing_rules", null, t => - { - t.HasComment("商品价格策略,支持会员价/时段价等。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductSku", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("规格属性 JSON(记录选项 ID)。"); - - b.Property("Barcode") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("条形码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("售价。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SkuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("SKU 编码。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("可售库存。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weight") - .HasPrecision(10, 3) - .HasColumnType("numeric(10,3)") - .HasComment("重量(千克)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SkuCode") - .IsUnique(); - - b.ToTable("product_skus", null, t => - { - t.HasComment("商品 SKU,记录具体规格组合价格。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Queues.Entities.QueueTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CalledAt") - .HasColumnType("timestamp with time zone") - .HasComment("叫号时间。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedWaitMinutes") - .HasColumnType("integer") - .HasComment("预计等待分钟。"); - - b.Property("ExpiredAt") - .HasColumnType("timestamp with time zone") - .HasComment("过号时间。"); - - b.Property("PartySize") - .HasColumnType("integer") - .HasComment("就餐人数。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("获取或设置所属门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNumber") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.HasIndex("TenantId", "StoreId", "TicketNumber") - .IsUnique(); - - b.ToTable("queue_tickets", null, t => - { - t.HasComment("排队叫号。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Reservations.Entities.Reservation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CheckInCode") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("核销码/到店码。"); - - b.Property("CheckedInAt") - .HasColumnType("timestamp with time zone") - .HasComment("实际签到时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("客户姓名。"); - - b.Property("CustomerPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PeopleCount") - .HasColumnType("integer") - .HasComment("用餐人数。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("预约号。"); - - b.Property("ReservationTime") - .HasColumnType("timestamp with time zone") - .HasComment("预约时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TablePreference") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌型/标签。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ReservationNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("reservations", null, t => - { - t.HasComment("预约/预订记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.Store", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ActivatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核通过时间。"); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("Announcement") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("门店公告。"); - - b.Property("AuditStatus") - .HasColumnType("integer") - .HasComment("审核状态。"); - - b.Property("BusinessHours") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("门店营业时段描述(备用字符串)。"); - - b.Property("BusinessLicenseImageUrl") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("门店营业执照图片地址(主体不一致模式使用)。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(50) - .HasColumnType("character varying(50)") - .HasComment("门店营业执照号(主体不一致模式使用)。"); - - b.Property("BusinessStatus") - .HasColumnType("integer") - .HasComment("经营状态。"); - - b.Property("CategoryId") - .HasColumnType("bigint") - .HasComment("行业类目 ID。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("ClosureReason") - .HasColumnType("integer") - .HasComment("歇业原因。"); - - b.Property("ClosureReasonText") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("歇业原因补充说明。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("门店编码,便于扫码及外部对接。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家或地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("门店海报。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryRadiusKm") - .HasPrecision(6, 2) - .HasColumnType("numeric(6,2)") - .HasComment("默认配送半径(公里)。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("门店描述或公告。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区县信息。"); - - b.Property("ForceCloseReason") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("强制关闭原因。"); - - b.Property("ForceClosedAt") - .HasColumnType("timestamp with time zone") - .HasComment("强制关闭时间。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("LegalRepresentative") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasComment("门店法人(主体不一致模式使用)。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("高德/腾讯地图经度。"); - - b.Property("ManagerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("门店负责人姓名。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("门店名称。"); - - b.Property("OwnershipType") - .HasColumnType("integer") - .HasComment("主体类型。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("RegisteredAddress") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("门店注册地址(主体不一致模式使用)。"); - - b.Property("RejectionReason") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("审核驳回原因。"); - - b.Property("SignboardImageUrl") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("门头招牌图 URL。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("门店当前运营状态。"); - - b.Property("SubmittedAt") - .HasColumnType("timestamp with time zone") - .HasComment("提交审核时间。"); - - b.Property("SupportsDelivery") - .HasColumnType("boolean") - .HasComment("是否支持配送。"); - - b.Property("SupportsDineIn") - .HasColumnType("boolean") - .HasComment("是否支持堂食。"); - - b.Property("SupportsPickup") - .HasColumnType("boolean") - .HasComment("是否支持自提。"); - - b.Property("SupportsQueueing") - .HasColumnType("boolean") - .HasComment("支持排队叫号。"); - - b.Property("SupportsReservation") - .HasColumnType("boolean") - .HasComment("支持预约。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("门店标签(逗号分隔)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("Longitude", "Latitude") - .HasFilter("\"Longitude\" IS NOT NULL AND \"Latitude\" IS NOT NULL"); - - b.HasIndex("MerchantId", "BusinessLicenseNumber") - .IsUnique() - .HasFilter("\"BusinessLicenseNumber\" IS NOT NULL AND \"Status\" <> 3"); - - b.HasIndex("TenantId", "AuditStatus"); - - b.HasIndex("TenantId", "BusinessStatus"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.HasIndex("TenantId", "MerchantId"); - - b.HasIndex("TenantId", "OwnershipType"); - - b.ToTable("stores", null, t => - { - t.HasComment("门店信息,承载营业配置与能力。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreAuditRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("操作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("NewStatus") - .HasColumnType("integer") - .HasComment("操作后状态。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasComment("操作人名称。"); - - b.Property("PreviousStatus") - .HasColumnType("integer") - .HasComment("操作前状态。"); - - b.Property("RejectionReason") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("驳回理由文本。"); - - b.Property("RejectionReasonId") - .HasColumnType("bigint") - .HasComment("驳回理由 ID。"); - - b.Property("Remarks") - .HasMaxLength(1000) - .HasColumnType("character varying(1000)") - .HasComment("备注。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("CreatedAt"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("store_audit_records", null, t => - { - t.HasComment("门店审核记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreBusinessHour", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CapacityLimit") - .HasColumnType("integer") - .HasComment("最大接待容量或单量限制。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DayOfWeek") - .HasColumnType("integer") - .HasComment("星期几,0 表示周日。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间(本地时间)。"); - - b.Property("HourType") - .HasColumnType("integer") - .HasComment("时段类型(正常营业、休息、预约等)。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间(本地时间)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "DayOfWeek"); - - b.ToTable("store_business_hours", null, t => - { - t.HasComment("门店营业时段配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreDeliveryZone", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("EstimatedMinutes") - .HasColumnType("integer") - .HasComment("预计送达分钟。"); - - b.Property("MinimumOrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("起送价。"); - - b.Property("PolygonGeoJson") - .IsRequired() - .HasColumnType("text") - .HasComment("GeoJSON 表示的多边形范围。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ZoneName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ZoneName"); - - b.ToTable("store_delivery_zones", null, t => - { - t.HasComment("门店配送范围配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreEmployeeShift", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("排班角色。"); - - b.Property("ShiftDate") - .HasColumnType("timestamp with time zone") - .HasComment("班次日期。"); - - b.Property("StaffId") - .HasColumnType("bigint") - .HasComment("员工标识。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ShiftDate", "StaffId") - .IsUnique(); - - b.ToTable("store_employee_shifts", null, t => - { - t.HasComment("门店员工排班记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreFee", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BaseDeliveryFee") - .HasPrecision(10, 2) - .HasColumnType("numeric(10,2)") - .HasComment("基础配送费(元)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("FixedPackagingFee") - .HasPrecision(10, 2) - .HasColumnType("numeric(10,2)") - .HasComment("固定打包费(总计模式有效)。"); - - b.Property("FreeDeliveryThreshold") - .HasPrecision(10, 2) - .HasColumnType("numeric(10,2)") - .HasComment("免配送费门槛。"); - - b.Property("MinimumOrderAmount") - .HasPrecision(10, 2) - .HasColumnType("numeric(10,2)") - .HasComment("起送费(元)。"); - - b.Property("PackagingFeeMode") - .HasColumnType("integer") - .HasComment("打包费模式。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "StoreId") - .IsUnique(); - - b.ToTable("store_fees", null, t => - { - t.HasComment("门店费用配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreHoliday", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Date") - .HasColumnType("timestamp with time zone") - .HasComment("日期。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsClosed") - .HasColumnType("boolean") - .HasComment("是否全天闭店。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("说明内容。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Date") - .IsUnique(); - - b.ToTable("store_holidays", null, t => - { - t.HasComment("门店休息日或特殊营业日。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSetting", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowDaysAhead") - .HasColumnType("integer") - .HasComment("可预约天数(含当天)。"); - - b.Property("AllowToday") - .HasColumnType("boolean") - .HasComment("是否允许当天自提。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultCutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("默认截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单笔自提最大份数。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId") - .IsUnique(); - - b.ToTable("store_pickup_settings", null, t => - { - t.HasComment("门店自提配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSlot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("容量(份数)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("当天结束时间(UTC)。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("档期名称。"); - - b.Property("ReservedCount") - .HasColumnType("integer") - .HasComment("已占用数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("当天开始时间(UTC)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weekdays") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("适用星期(逗号分隔 1-7)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("store_pickup_slots", null, t => - { - t.HasComment("门店自提档期。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreQualification", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DocumentNumber") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasComment("证照编号。"); - - b.Property("ExpiresAt") - .HasColumnType("date") - .HasComment("到期日期。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("证照文件 URL。"); - - b.Property("IssuedAt") - .HasColumnType("date") - .HasComment("签发日期。"); - - b.Property("QualificationType") - .HasColumnType("integer") - .HasComment("资质类型。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(100) - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("ExpiresAt") - .HasFilter("\"ExpiresAt\" IS NOT NULL"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("store_qualifications", null, t => - { - t.HasComment("门店资质证照。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTable", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AreaId") - .HasColumnType("bigint") - .HasComment("所在区域 ID。"); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("可容纳人数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("QrCodeUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("桌码二维码地址。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前桌台状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("桌码。"); - - b.Property("Tags") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("桌台标签(堂食、快餐等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "TableCode") - .IsUnique(); - - b.ToTable("store_tables", null, t => - { - t.HasComment("桌台信息与二维码绑定。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTableArea", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("区域描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name") - .IsUnique(); - - b.ToTable("store_table_areas", null, t => - { - t.HasComment("门店桌台区域配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.QuotaPackage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("描述。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否上架。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("配额包名称。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("价格。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型。"); - - b.Property("QuotaValue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配额数值。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("排序。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("QuotaType", "IsActive", "SortOrder"); - - b.ToTable("quota_packages", null, t => - { - t.HasComment("配额包定义(平台提供的可购买配额包)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.Tenant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("text") - .HasComment("详细地址信息。"); - - b.Property("City") - .HasColumnType("text") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("租户短编码,作为跨系统引用的唯一标识。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("主联系人邮箱。"); - - b.Property("ContactName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("主联系人姓名。"); - - b.Property("ContactPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("主联系人电话。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家/地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("品牌海报或封面图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("服务生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("服务到期时间(UTC)。"); - - b.Property("Industry") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所属行业,如餐饮、零售等。"); - - b.Property("LegalEntityName") - .HasColumnType("text") - .HasComment("法人或公司主体名称。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("LOGO 图片地址。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("租户全称或品牌名称。"); - - b.Property("OperatingMode") - .HasColumnType("integer") - .HasComment("经营模式(同一主体/不同主体)。"); - - b.Property("PrimaryOwnerUserId") - .HasColumnType("bigint") - .HasComment("系统内对应的租户所有者账号 ID。"); - - b.Property("Province") - .HasColumnType("text") - .HasComment("所在省份或州。"); - - b.Property("Remarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息,用于运营记录特殊说明。"); - - b.Property("ShortName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("对外展示的简称。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("租户当前状态,涵盖审核、启用、停用等场景。"); - - b.Property("SuspendedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次暂停服务时间。"); - - b.Property("SuspensionReason") - .HasColumnType("text") - .HasComment("暂停或终止的原因说明。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("业务标签集合(逗号分隔)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Website") - .HasColumnType("text") - .HasComment("官网或主要宣传链接。"); - - b.HasKey("Id"); - - b.HasIndex("Code") - .IsUnique(); - - b.HasIndex("ContactPhone") - .IsUnique(); - - b.ToTable("tenants", null, t => - { - t.HasComment("平台租户信息,描述租户的生命周期与基础资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementType") - .HasColumnType("integer") - .HasComment("公告类型。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("公告正文(可为 Markdown/HTML,前端自行渲染)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("失效时间(UTC),为空表示长期有效。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否启用(已弃用,迁移期保留)。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("展示优先级,数值越大越靠前。"); - - b.Property("PublishedAt") - .HasColumnType("timestamp with time zone") - .HasComment("实际发布时间(UTC)。"); - - b.Property("PublisherScope") - .HasColumnType("integer") - .HasComment("发布者范围。"); - - b.Property("PublisherUserId") - .HasColumnType("bigint") - .HasComment("发布者用户 ID(平台或租户后台账号)。"); - - b.Property("RevokedAt") - .HasColumnType("timestamp with time zone") - .HasComment("撤销时间(UTC)。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("ScheduledPublishAt") - .HasColumnType("timestamp with time zone") - .HasComment("预定发布时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("公告状态。"); - - b.Property("TargetParameters") - .HasColumnType("text") - .HasComment("目标受众参数(JSON)。"); - - b.Property("TargetType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("目标受众类型。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("公告标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("Status", "EffectiveFrom") - .HasFilter("\"TenantId\" = 0"); - - b.HasIndex("TenantId", "AnnouncementType", "IsActive"); - - b.HasIndex("TenantId", "EffectiveFrom", "EffectiveTo"); - - b.HasIndex("TenantId", "Status", "EffectiveFrom"); - - b.ToTable("tenant_announcements", null, t => - { - t.HasComment("租户公告。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncementRead", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementId") - .HasColumnType("bigint") - .HasComment("公告 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("已读时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("已读用户 ID(后台账号),为空表示租户级已读。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AnnouncementId", "UserId") - .IsUnique(); - - b.ToTable("tenant_announcement_reads", null, t => - { - t.HasComment("租户公告已读记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantBillingStatement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AmountDue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额(原始金额)。"); - - b.Property("AmountPaid") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("BillingType") - .HasColumnType("integer") - .HasComment("账单类型(订阅账单/配额包账单/手动账单/续费账单)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Currency") - .IsRequired() - .ValueGeneratedOnAdd() - .HasMaxLength(8) - .HasColumnType("character varying(8)") - .HasDefaultValue("CNY") - .HasComment("货币类型(默认 CNY)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("折扣金额。"); - - b.Property("DueDate") - .HasColumnType("timestamp with time zone") - .HasComment("到期日。"); - - b.Property("LineItemsJson") - .HasColumnType("text") - .HasComment("账单明细 JSON,记录各项费用。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息(如:人工备注、取消原因等)。"); - - b.Property("OverdueNotifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("逾期通知时间。"); - - b.Property("PeriodEnd") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期结束时间。"); - - b.Property("PeriodStart") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期开始时间。"); - - b.Property("ReminderSentAt") - .HasColumnType("timestamp with time zone") - .HasComment("提醒发送时间(续费提醒、逾期提醒等)。"); - - b.Property("StatementNo") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("账单编号,供对账查询。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前付款状态。"); - - b.Property("SubscriptionId") - .HasColumnType("bigint") - .HasComment("关联的订阅 ID(仅当 BillingType 为 Subscription 或 Renewal 时有值)。"); - - b.Property("TaxAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("税费金额。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("CreatedAt") - .HasDatabaseName("idx_billing_created_at"); - - b.HasIndex("Status", "DueDate") - .HasDatabaseName("idx_billing_status_duedate") - .HasFilter("\"Status\" IN (0, 2)"); - - b.HasIndex("TenantId", "StatementNo") - .IsUnique(); - - b.HasIndex("TenantId", "Status", "DueDate") - .HasDatabaseName("idx_billing_tenant_status_duedate"); - - b.ToTable("tenant_billing_statements", null, t => - { - t.HasComment("租户账单,用于呈现周期性收费。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantNotification", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("发布通道(站内、邮件、短信等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("通知正文。"); - - b.Property("MetadataJson") - .HasColumnType("text") - .HasComment("附加元数据 JSON。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("租户是否已阅读。"); - - b.Property("SentAt") - .HasColumnType("timestamp with time zone") - .HasComment("推送时间。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("通知重要级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("通知标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Channel", "SentAt"); - - b.ToTable("tenant_notifications", null, t => - { - t.HasComment("面向租户的站内通知或消息推送。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantPackage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("套餐描述,包含适用场景、权益等。"); - - b.Property("FeaturePoliciesJson") - .HasColumnType("text") - .HasComment("权益明细 JSON,记录自定义特性开关。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否仍启用(平台控制)。"); - - b.Property("IsAllowNewTenantPurchase") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否允许新租户购买/选择(仅影响新购)。"); - - b.Property("IsPublicVisible") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否对外可见(展示页/套餐列表可见性)。"); - - b.Property("IsRecommended") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false) - .HasComment("是否推荐展示(运营推荐标识)。"); - - b.Property("MaxAccountCount") - .HasColumnType("integer") - .HasComment("允许创建的最大账号数。"); - - b.Property("MaxDeliveryOrders") - .HasColumnType("integer") - .HasComment("每月可调用的配送单数量上限。"); - - b.Property("MaxSmsCredits") - .HasColumnType("integer") - .HasComment("每月短信额度上限。"); - - b.Property("MaxStorageGb") - .HasColumnType("integer") - .HasComment("存储容量上限(GB)。"); - - b.Property("MaxStoreCount") - .HasColumnType("integer") - .HasComment("允许的最大门店数。"); - - b.Property("MonthlyPrice") - .HasColumnType("numeric") - .HasComment("月付价格,单位:人民币元。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("套餐名称,展示给租户的简称。"); - - b.Property("PackageType") - .HasColumnType("integer") - .HasComment("套餐分类(试用、标准、旗舰等)。"); - - b.Property("PublishStatus") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("发布状态:0=草稿,1=已发布。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("展示排序,数值越小越靠前。"); - - b.PrimitiveCollection("Tags") - .IsRequired() - .HasColumnType("text[]") - .HasComment("套餐标签(用于展示与对比页)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("YearlyPrice") - .HasColumnType("numeric") - .HasComment("年付价格,单位:人民币元。"); - - b.HasKey("Id"); - - b.HasIndex("IsActive", "SortOrder"); - - b.HasIndex("PublishStatus", "IsActive", "IsPublicVisible", "IsAllowNewTenantPurchase", "SortOrder"); - - b.ToTable("tenant_packages", null, t => - { - t.HasComment("平台提供的租户套餐定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantPayment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("支付金额。"); - - b.Property("BillingStatementId") - .HasColumnType("bigint") - .HasComment("关联的账单 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Method") - .HasColumnType("integer") - .HasComment("支付方式。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付时间。"); - - b.Property("ProofUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("支付凭证 URL。"); - - b.Property("RefundReason") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("退款原因。"); - - b.Property("RefundedAt") - .HasColumnType("timestamp with time zone") - .HasComment("退款时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TransactionNo") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("交易号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("VerifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核时间。"); - - b.Property("VerifiedBy") - .HasColumnType("bigint") - .HasComment("审核人 ID(管理员)。"); - - b.HasKey("Id"); - - b.HasIndex("TransactionNo") - .HasDatabaseName("idx_payment_transaction_no") - .HasFilter("\"TransactionNo\" IS NOT NULL"); - - b.HasIndex("BillingStatementId", "PaidAt") - .HasDatabaseName("idx_payment_billing_paidat"); - - b.HasIndex("TenantId", "BillingStatementId"); - - b.ToTable("tenant_payments", null, t => - { - t.HasComment("租户支付记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaPackagePurchase", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiredAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(可选)。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("购买价格。"); - - b.Property("PurchasedAt") - .HasColumnType("timestamp with time zone") - .HasComment("购买时间。"); - - b.Property("QuotaPackageId") - .HasColumnType("bigint") - .HasComment("配额包 ID。"); - - b.Property("QuotaValue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("购买时的配额值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "QuotaPackageId", "PurchasedAt"); - - b.ToTable("tenant_quota_package_purchases", null, t => - { - t.HasComment("租户配额包购买记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaUsage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LastResetAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次重置时间。"); - - b.Property("LimitValue") - .HasColumnType("numeric") - .HasComment("当前配额上限。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型,例如门店数、短信条数等。"); - - b.Property("ResetCycle") - .HasColumnType("text") - .HasComment("配额刷新周期描述(如月、年)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedValue") - .HasColumnType("numeric") - .HasComment("已消耗的数量。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "QuotaType") - .IsUnique(); - - b.ToTable("tenant_quota_usages", null, t => - { - t.HasComment("租户配额使用情况快照。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaUsageHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChangeAmount") - .HasColumnType("numeric") - .HasComment("变更量(可选)。"); - - b.Property("ChangeReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("变更原因(可选)。"); - - b.Property("ChangeType") - .HasColumnType("integer") - .HasComment("变更类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LimitValue") - .HasColumnType("numeric") - .HasComment("限额值(记录时刻的快照)。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型。"); - - b.Property("RecordedAt") - .HasColumnType("timestamp with time zone") - .HasComment("记录时间(UTC)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedValue") - .HasColumnType("numeric") - .HasComment("已使用值(记录时刻的快照)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "RecordedAt"); - - b.HasIndex("TenantId", "QuotaType", "RecordedAt"); - - b.ToTable("tenant_quota_usage_histories", null, t => - { - t.HasComment("租户配额使用历史记录(用于追踪配额上下限与使用量的时间序列变化)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantReviewClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ClaimedAt") - .HasColumnType("timestamp with time zone") - .HasComment("领取时间(UTC)。"); - - b.Property("ClaimedBy") - .HasColumnType("bigint") - .HasComment("领取人用户 ID。"); - - b.Property("ClaimedByName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("领取人名称(展示用快照)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReleasedAt") - .HasColumnType("timestamp with time zone") - .HasComment("释放时间(UTC),未释放时为 null。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("被领取的租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("ClaimedBy"); - - b.HasIndex("TenantId") - .IsUnique() - .HasFilter("\"ReleasedAt\" IS NULL AND \"DeletedAt\" IS NULL"); - - b.ToTable("tenant_review_claims", null, t => - { - t.HasComment("租户入驻审核领取记录(防止多管理员并发审核)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscription", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AutoRenew") - .HasColumnType("boolean") - .HasComment("是否开启自动续费。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("订阅生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("订阅到期时间(UTC)。"); - - b.Property("NextBillingDate") - .HasColumnType("timestamp with time zone") - .HasComment("下一个计费时间,配合自动续费使用。"); - - b.Property("Notes") - .HasColumnType("text") - .HasComment("运营备注信息。"); - - b.Property("ScheduledPackageId") - .HasColumnType("bigint") - .HasComment("若已排期升降配,对应的新套餐 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("订阅当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TenantPackageId") - .HasColumnType("bigint") - .HasComment("当前订阅关联的套餐标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantPackageId"); - - b.ToTable("tenant_subscriptions", null, t => - { - t.HasComment("租户套餐订阅记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscriptionHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasColumnType("numeric") - .HasComment("相关费用。"); - - b.Property("ChangeType") - .HasColumnType("integer") - .HasComment("变更类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Currency") - .HasMaxLength(8) - .HasColumnType("character varying(8)") - .HasComment("币种。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("FromPackageId") - .HasColumnType("bigint") - .HasComment("原套餐 ID。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("租户标识。"); - - b.Property("TenantSubscriptionId") - .HasColumnType("bigint") - .HasComment("对应的订阅 ID。"); - - b.Property("ToPackageId") - .HasColumnType("bigint") - .HasComment("新套餐 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantSubscriptionId"); - - b.ToTable("tenant_subscription_histories", null, t => - { - t.HasComment("租户套餐订阅变更记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantVerificationProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdditionalDataJson") - .HasColumnType("text") - .HasComment("附加资料(JSON)。"); - - b.Property("BankAccountName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("开户名。"); - - b.Property("BankAccountNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("银行账号。"); - - b.Property("BankName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("银行名称。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照编号。"); - - b.Property("BusinessLicenseUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营业执照文件地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LegalPersonIdBackUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证反面。"); - - b.Property("LegalPersonIdFrontUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证正面。"); - - b.Property("LegalPersonIdNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("法人身份证号。"); - - b.Property("LegalPersonName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人姓名。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注。"); - - b.Property("ReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核时间。"); - - b.Property("ReviewedBy") - .HasColumnType("bigint") - .HasComment("审核人 ID。"); - - b.Property("ReviewedByName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("审核人姓名。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("实名状态。"); - - b.Property("SubmittedAt") - .HasColumnType("timestamp with time zone") - .HasComment("提交时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("对应的租户标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId") - .IsUnique(); - - b.ToTable("tenant_verification_profiles", null, t => - { - t.HasComment("租户实名认证资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.HasOne("TakeoutSaaS.Domain.Orders.Entities.Order", null) - .WithMany() - .HasForeignKey("OrderId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20260120045217_UpdateStoreQualificationDateFields.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20260120045217_UpdateStoreQualificationDateFields.cs deleted file mode 100644 index 9fb0b77..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20260120045217_UpdateStoreQualificationDateFields.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - /// - public partial class UpdateStoreQualificationDateFields : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "IssuedAt", - table: "store_qualifications", - type: "date", - nullable: true, - comment: "签发日期。", - oldClrType: typeof(DateTime), - oldType: "timestamp with time zone", - oldNullable: true, - oldComment: "签发日期。"); - - migrationBuilder.AlterColumn( - name: "ExpiresAt", - table: "store_qualifications", - type: "date", - nullable: true, - comment: "到期日期。", - oldClrType: typeof(DateTime), - oldType: "timestamp with time zone", - oldNullable: true, - oldComment: "到期日期。"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "IssuedAt", - table: "store_qualifications", - type: "timestamp with time zone", - nullable: true, - comment: "签发日期。", - oldClrType: typeof(DateOnly), - oldType: "date", - oldNullable: true, - oldComment: "签发日期。"); - - migrationBuilder.AlterColumn( - name: "ExpiresAt", - table: "store_qualifications", - type: "timestamp with time zone", - nullable: true, - comment: "到期日期。", - oldClrType: typeof(DateOnly), - oldType: "date", - oldNullable: true, - oldComment: "到期日期。"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20260120090508_ExtendStoreHolidayForTemporaryHours.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20260120090508_ExtendStoreHolidayForTemporaryHours.Designer.cs deleted file mode 100644 index 1301696..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20260120090508_ExtendStoreHolidayForTemporaryHours.Designer.cs +++ /dev/null @@ -1,7416 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.App.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - [DbContext(typeof(TakeoutAppDbContext))] - [Migration("20260120090508_ExtendStoreHolidayForTemporaryHours")] - partial class ExtendStoreHolidayForTemporaryHours - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.1") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricAlertRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionJson") - .IsRequired() - .HasColumnType("text") - .HasComment("触发条件 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Enabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("关联指标。"); - - b.Property("NotificationChannels") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("通知渠道。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("告警级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "Severity"); - - b.ToTable("metric_alert_rules", null, t => - { - t.HasComment("指标告警规则。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricDefinition", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("指标编码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultAggregation") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("默认聚合方式。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("说明。"); - - b.Property("DimensionsJson") - .HasColumnType("text") - .HasComment("维度描述 JSON。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("指标名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("metric_definitions", null, t => - { - t.HasComment("指标定义,描述可观测的数据点。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricSnapshot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DimensionKey") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("维度键(JSON)。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("指标定义 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Value") - .HasPrecision(18, 4) - .HasColumnType("numeric(18,4)") - .HasComment("数值。"); - - b.Property("WindowEnd") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口结束。"); - - b.Property("WindowStart") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口开始。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "DimensionKey", "WindowStart", "WindowEnd") - .IsUnique(); - - b.ToTable("metric_snapshots", null, t => - { - t.HasComment("指标快照,用于大盘展示。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.Coupon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("券码或序列号。"); - - b.Property("CouponTemplateId") - .HasColumnType("bigint") - .HasComment("模板标识。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("发放时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID(已使用时记录)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedAt") - .HasColumnType("timestamp with time zone") - .HasComment("使用时间。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("归属用户。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("coupons", null, t => - { - t.HasComment("用户领取的券。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.CouponTemplate", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowStack") - .HasColumnType("boolean") - .HasComment("是否允许叠加其他优惠。"); - - b.Property("ChannelsJson") - .HasColumnType("text") - .HasComment("发放渠道(JSON)。"); - - b.Property("ClaimedQuantity") - .HasColumnType("integer") - .HasComment("已领取数量。"); - - b.Property("CouponType") - .HasColumnType("integer") - .HasComment("券类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("DiscountCap") - .HasColumnType("numeric") - .HasComment("折扣上限(针对折扣券)。"); - - b.Property("MinimumSpend") - .HasColumnType("numeric") - .HasComment("最低消费门槛。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("模板名称。"); - - b.Property("ProductScopeJson") - .HasColumnType("text") - .HasComment("适用品类或商品范围(JSON)。"); - - b.Property("RelativeValidDays") - .HasColumnType("integer") - .HasComment("有效天数(相对发放时间)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreScopeJson") - .HasColumnType("text") - .HasComment("适用门店 ID 集合(JSON)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TotalQuantity") - .HasColumnType("integer") - .HasComment("总发放数量上限。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ValidFrom") - .HasColumnType("timestamp with time zone") - .HasComment("可用开始时间。"); - - b.Property("ValidTo") - .HasColumnType("timestamp with time zone") - .HasComment("可用结束时间。"); - - b.Property("Value") - .HasColumnType("numeric") - .HasComment("面值或折扣额度。"); - - b.HasKey("Id"); - - b.ToTable("coupon_templates", null, t => - { - t.HasComment("优惠券模板。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.PromotionCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AudienceDescription") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("目标人群描述。"); - - b.Property("BannerUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营销素材(如 banner)。"); - - b.Property("Budget") - .HasColumnType("numeric") - .HasComment("预算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("PromotionType") - .HasColumnType("integer") - .HasComment("活动类型。"); - - b.Property("RulesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("活动规则 JSON。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("活动状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("promotion_campaigns", null, t => - { - t.HasComment("营销活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChatSessionId") - .HasColumnType("bigint") - .HasComment("会话标识。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("消息内容。"); - - b.Property("ContentType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("消息类型(文字/图片/语音等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRead") - .HasColumnType("boolean") - .HasComment("是否已读。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("读取时间。"); - - b.Property("SenderType") - .HasColumnType("integer") - .HasComment("发送方类型。"); - - b.Property("SenderUserId") - .HasColumnType("bigint") - .HasComment("发送方用户 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ChatSessionId", "CreatedAt"); - - b.ToTable("chat_messages", null, t => - { - t.HasComment("会话消息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AgentUserId") - .HasColumnType("bigint") - .HasComment("当前客服员工 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("顾客用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndedAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("IsBotActive") - .HasColumnType("boolean") - .HasComment("是否机器人接待中。"); - - b.Property("SessionCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话编号。"); - - b.Property("StartedAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店(可空为平台)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionCode") - .IsUnique(); - - b.ToTable("chat_sessions", null, t => - { - t.HasComment("客服会话。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.SupportTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AssignedAgentId") - .HasColumnType("bigint") - .HasComment("指派的客服。"); - - b.Property("ClosedAt") - .HasColumnType("timestamp with time zone") - .HasComment("关闭时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("客户用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .IsRequired() - .HasColumnType("text") - .HasComment("工单详情。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单(如有)。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("优先级。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("Subject") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("工单主题。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("工单编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TicketNo") - .IsUnique(); - - b.ToTable("support_tickets", null, t => - { - t.HasComment("客服工单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.TicketComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttachmentsJson") - .HasColumnType("text") - .HasComment("附件 JSON。"); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人 ID。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsInternal") - .HasColumnType("boolean") - .HasComment("是否内部备注。"); - - b.Property("SupportTicketId") - .HasColumnType("bigint") - .HasComment("工单标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SupportTicketId"); - - b.ToTable("ticket_comments", null, t => - { - t.HasComment("工单评论/流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryEvent", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryOrderId") - .HasColumnType("bigint") - .HasComment("配送单标识。"); - - b.Property("EventType") - .HasColumnType("integer") - .HasComment("事件类型。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("事件描述。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始数据 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DeliveryOrderId", "EventType"); - - b.ToTable("delivery_events", null, t => - { - t.HasComment("配送状态事件流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CourierName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("骑手姓名。"); - - b.Property("CourierPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("骑手电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveredAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("DispatchedAt") - .HasColumnType("timestamp with time zone") - .HasComment("下发时间。"); - - b.Property("FailureReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("异常原因。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("获取或设置关联订单 ID。"); - - b.Property("PickedUpAt") - .HasColumnType("timestamp with time zone") - .HasComment("取餐时间。"); - - b.Property("Provider") - .HasColumnType("integer") - .HasComment("配送服务商。"); - - b.Property("ProviderOrderId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方配送单号。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId") - .IsUnique(); - - b.ToTable("delivery_orders", null, t => - { - t.HasComment("配送单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliateOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("推广人标识。"); - - b.Property("BuyerUserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedCommission") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("预计佣金。"); - - b.Property("OrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("订单金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("SettledAt") - .HasColumnType("timestamp with time zone") - .HasComment("结算完成时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "OrderId") - .IsUnique(); - - b.ToTable("affiliate_orders", null, t => - { - t.HasComment("分销订单记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePartner", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChannelType") - .HasColumnType("integer") - .HasComment("渠道类型。"); - - b.Property("CommissionRate") - .HasColumnType("numeric") - .HasComment("分成比例(0-1)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称或渠道名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID(如绑定平台账号)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DisplayName"); - - b.ToTable("affiliate_partners", null, t => - { - t.HasComment("分销/推广合作伙伴。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePayout", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("合作伙伴标识。"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("结算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("打款时间。"); - - b.Property("Period") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("结算周期描述。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "Period") - .IsUnique(); - - b.ToTable("affiliate_payouts", null, t => - { - t.HasComment("佣金结算记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowMakeupCount") - .HasColumnType("integer") - .HasComment("支持补签次数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("活动描述。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("结束日期。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("RewardsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("连签奖励 JSON。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("开始日期。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name"); - - b.ToTable("checkin_campaigns", null, t => - { - t.HasComment("签到活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CheckInCampaignId") - .HasColumnType("bigint") - .HasComment("活动标识。"); - - b.Property("CheckInDate") - .HasColumnType("timestamp with time zone") - .HasComment("签到日期(本地)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsMakeup") - .HasColumnType("boolean") - .HasComment("是否补签。"); - - b.Property("RewardJson") - .IsRequired() - .HasColumnType("text") - .HasComment("获得奖励 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "CheckInCampaignId", "UserId", "CheckInDate") - .IsUnique(); - - b.ToTable("checkin_records", null, t => - { - t.HasComment("用户签到记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsDeleted") - .HasColumnType("boolean") - .HasComment("状态。"); - - b.Property("ParentId") - .HasColumnType("bigint") - .HasComment("父级评论 ID。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "CreatedAt"); - - b.ToTable("community_comments", null, t => - { - t.HasComment("社区评论。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityPost", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("作者用户 ID。"); - - b.Property("CommentCount") - .HasColumnType("integer") - .HasComment("评论数。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LikeCount") - .HasColumnType("integer") - .HasComment("点赞数。"); - - b.Property("MediaJson") - .HasColumnType("text") - .HasComment("媒体资源 JSON。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AuthorUserId", "CreatedAt"); - - b.ToTable("community_posts", null, t => - { - t.HasComment("社区动态。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityReaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态 ID。"); - - b.Property("ReactedAt") - .HasColumnType("timestamp with time zone") - .HasComment("时间戳。"); - - b.Property("ReactionType") - .HasColumnType("integer") - .HasComment("反应类型。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "UserId") - .IsUnique(); - - b.ToTable("community_reactions", null, t => - { - t.HasComment("社区互动反馈。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentCount") - .HasColumnType("integer") - .HasComment("当前已参与人数。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("GroupOrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("拼单编号。"); - - b.Property("GroupPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("拼团价格。"); - - b.Property("LeaderUserId") - .HasColumnType("bigint") - .HasComment("团长用户 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("关联商品或套餐。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("拼团状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("SucceededAt") - .HasColumnType("timestamp with time zone") - .HasComment("成团时间。"); - - b.Property("TargetCount") - .HasColumnType("integer") - .HasComment("成团需要的人数。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderNo") - .IsUnique(); - - b.ToTable("group_orders", null, t => - { - t.HasComment("拼单活动。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupParticipant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GroupOrderId") - .HasColumnType("bigint") - .HasComment("拼单活动标识。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("参与时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("对应订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("参与状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderId", "UserId") - .IsUnique(); - - b.ToTable("group_participants", null, t => - { - t.HasComment("拼单参与者。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryAdjustment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdjustmentType") - .HasColumnType("integer") - .HasComment("调整类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("InventoryItemId") - .HasColumnType("bigint") - .HasComment("对应的库存记录标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("调整数量,正数增加,负数减少。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("原因说明。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "InventoryItemId", "OccurredAt"); - - b.ToTable("inventory_adjustments", null, t => - { - t.HasComment("库存调整记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryBatch", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("ProductionDate") - .HasColumnType("timestamp with time zone") - .HasComment("生产日期。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("入库数量。"); - - b.Property("RemainingQuantity") - .HasColumnType("integer") - .HasComment("剩余数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber") - .IsUnique(); - - b.ToTable("inventory_batches", null, t => - { - t.HasComment("SKU 批次信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchConsumeStrategy") - .HasColumnType("integer") - .HasComment("批次扣减策略。"); - - b.Property("BatchNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号,可为空表示混批。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售商品。"); - - b.Property("IsSoldOut") - .HasColumnType("boolean") - .HasComment("是否标记售罄。"); - - b.Property("Location") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("储位或仓位信息。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单品限购(覆盖商品级 MaxQuantityPerOrder)。"); - - b.Property("PresaleCapacity") - .HasColumnType("integer") - .HasComment("预售名额(上限)。"); - - b.Property("PresaleEndTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售结束时间(UTC)。"); - - b.Property("PresaleLocked") - .HasColumnType("integer") - .HasComment("当前预售已锁定数量。"); - - b.Property("PresaleStartTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售开始时间(UTC)。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("QuantityOnHand") - .HasColumnType("integer") - .HasComment("可用库存。"); - - b.Property("QuantityReserved") - .HasColumnType("integer") - .HasComment("已锁定库存(订单占用)。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("SafetyStock") - .HasColumnType("integer") - .HasComment("安全库存阈值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber"); - - b.ToTable("inventory_items", null, t => - { - t.HasComment("SKU 在门店的库存信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryLockRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("IdempotencyKey") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("幂等键。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售锁定。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU ID。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("锁定数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("锁定状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "IdempotencyKey") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "Status"); - - b.ToTable("inventory_lock_records", null, t => - { - t.HasComment("库存锁定记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberPointLedger", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BalanceAfterChange") - .HasColumnType("integer") - .HasComment("变动后余额。"); - - b.Property("ChangeAmount") - .HasColumnType("integer") - .HasComment("变动数量,可为负值。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(如适用)。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Reason") - .HasColumnType("integer") - .HasComment("变动原因。"); - - b.Property("SourceId") - .HasColumnType("bigint") - .HasComment("来源 ID(订单、活动等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_point_ledgers", null, t => - { - t.HasComment("积分变动流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AvatarUrl") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像。"); - - b.Property("BirthDate") - .HasColumnType("timestamp with time zone") - .HasComment("生日。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GrowthValue") - .HasColumnType("integer") - .HasComment("成长值/经验值。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("注册时间。"); - - b.Property("MemberTierId") - .HasColumnType("bigint") - .HasComment("当前会员等级 ID。"); - - b.Property("Mobile") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("Nickname") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称。"); - - b.Property("PointsBalance") - .HasColumnType("integer") - .HasComment("会员积分余额。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会员状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Mobile") - .IsUnique(); - - b.ToTable("member_profiles", null, t => - { - t.HasComment("会员档案。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberTier", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BenefitsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("等级权益(JSON)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("等级名称。"); - - b.Property("RequiredGrowth") - .HasColumnType("integer") - .HasComment("所需成长值。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("member_tiers", null, t => - { - t.HasComment("会员等级定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.Merchant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("ApprovedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核通过时间。"); - - b.Property("ApprovedBy") - .HasColumnType("bigint") - .HasComment("审核通过人。"); - - b.Property("BrandAlias") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("品牌简称或别名。"); - - b.Property("BrandName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("品牌名称(对外展示)。"); - - b.Property("BusinessLicenseImageUrl") - .HasColumnType("text") - .HasComment("营业执照扫描件地址。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照号。"); - - b.Property("Category") - .HasColumnType("text") - .HasComment("品牌所属品类,如火锅、咖啡等。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("ClaimExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("领取过期时间。"); - - b.Property("ClaimedAt") - .HasColumnType("timestamp with time zone") - .HasComment("领取时间。"); - - b.Property("ClaimedBy") - .HasColumnType("bigint") - .HasComment("当前领取人。"); - - b.Property("ClaimedByName") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasComment("当前领取人姓名。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("联系邮箱。"); - - b.Property("ContactPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在区县。"); - - b.Property("FrozenAt") - .HasColumnType("timestamp with time zone") - .HasComment("冻结时间。"); - - b.Property("FrozenReason") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("冻结原因。"); - - b.Property("IsFrozen") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false) - .HasComment("是否冻结业务。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("入驻时间。"); - - b.Property("LastReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次审核时间。"); - - b.Property("LastReviewedBy") - .HasColumnType("bigint") - .HasComment("最近一次审核人。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度信息。"); - - b.Property("LegalPerson") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人或负责人姓名。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("品牌 Logo。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度信息。"); - - b.Property("OperatingMode") - .HasColumnType("integer") - .HasComment("经营模式(同一主体/不同主体)。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注或驳回原因。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制版本。"); - - b.Property("ServicePhone") - .HasColumnType("text") - .HasComment("客服电话。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("入驻状态。"); - - b.Property("SupportEmail") - .HasColumnType("text") - .HasComment("客服邮箱。"); - - b.Property("TaxNumber") - .HasColumnType("text") - .HasComment("税号/统一社会信用代码。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("ClaimedBy"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Status"); - - b.ToTable("merchants", null, t => - { - t.HasComment("商户主体信息,承载入驻和资质审核结果。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("显示顺序,越小越靠前。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否可用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("类目名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("merchant_categories", null, t => - { - t.HasComment("商户可选类目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantContract", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ContractNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("合同编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同结束时间。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("合同文件存储地址。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("SignedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签署时间。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("合同状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TerminatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("终止时间。"); - - b.Property("TerminationReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("终止原因。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "ContractNumber") - .IsUnique(); - - b.ToTable("merchant_contracts", null, t => - { - t.HasComment("商户合同记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantDocument", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DocumentNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("证照编号。"); - - b.Property("DocumentType") - .HasColumnType("integer") - .HasComment("证照类型。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期日期。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("证照文件链接。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签发日期。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Remarks") - .HasColumnType("text") - .HasComment("审核备注或驳回原因。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("审核状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "DocumentType"); - - b.ToTable("merchant_documents", null, t => - { - t.HasComment("商户提交的资质或证照材料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantStaff", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Email") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("邮箱地址。"); - - b.Property("IdentityUserId") - .HasColumnType("bigint") - .HasComment("登录账号 ID(指向统一身份体系)。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("员工姓名。"); - - b.Property("PermissionsJson") - .HasColumnType("text") - .HasComment("自定义权限(JSON)。"); - - b.Property("Phone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("员工角色类型。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("员工状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("可选的关联门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "Phone"); - - b.ToTable("merchant_staff", null, t => - { - t.HasComment("商户员工账号,支持门店维度分配。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.MapLocation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Landmark") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("打车/导航落点描述。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("名称。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店 ID,可空表示独立 POI。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("map_locations", null, t => - { - t.HasComment("地图 POI 信息,用于门店定位和推荐。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.NavigationRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("来源通道(小程序、H5 等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("请求时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TargetApp") - .HasColumnType("integer") - .HasComment("跳转的地图应用。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId", "RequestedAt"); - - b.ToTable("navigation_requests", null, t => - { - t.HasComment("用户发起的导航请求日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("扩展 JSON(规格、加料选项等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品或 SKU 标识。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称快照。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("自定义备注(口味要求)。"); - - b.Property("ShoppingCartId") - .HasColumnType("bigint") - .HasComment("所属购物车标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价快照。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ShoppingCartId"); - - b.ToTable("cart_items", null, t => - { - t.HasComment("购物车条目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItemAddon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CartItemId") - .HasColumnType("bigint") - .HasComment("所属购物车条目。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("OptionId") - .HasColumnType("bigint") - .HasComment("选项 ID(可对应 ProductAddonOption)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("cart_item_addons", null, t => - { - t.HasComment("购物车条目的加料/附加项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CheckoutSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("SessionToken") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话 Token。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.Property("ValidationResultJson") - .IsRequired() - .HasColumnType("text") - .HasComment("校验结果明细 JSON。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionToken") - .IsUnique(); - - b.ToTable("checkout_sessions", null, t => - { - t.HasComment("结账会话,记录校验上下文。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.ShoppingCart", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryPreference") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("履约方式(堂食/自提/配送)缓存。"); - - b.Property("LastModifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次修改时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("购物车状态,包含正常/锁定。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableContext") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌码或场景标识(扫码点餐)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId") - .IsUnique(); - - b.ToTable("shopping_carts", null, t => - { - t.HasComment("用户购物车,按租户/门店隔离。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.Order", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("取消原因。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("下单渠道。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("顾客姓名。"); - - b.Property("CustomerPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("顾客手机号。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryType") - .HasColumnType("integer") - .HasComment("履约类型。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("优惠金额。"); - - b.Property("FinishedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("ItemsAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("商品总额。"); - - b.Property("OrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("订单号。"); - - b.Property("PaidAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付时间。"); - - b.Property("PayableAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额。"); - - b.Property("PaymentStatus") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("QueueNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队号(如有)。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationId") - .HasColumnType("bigint") - .HasComment("预约 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TableNo") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("就餐桌号。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "Status"); - - b.ToTable("orders", null, t => - { - t.HasComment("交易订单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("自定义属性 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("折扣金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品 ID。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("SkuName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("SKU/规格描述。"); - - b.Property("SubTotal") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("小计。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("单位。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("OrderId"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("order_items", null, t => - { - t.HasComment("订单明细。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderStatusHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注信息。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识(可为空表示系统)。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("变更后的状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId", "OccurredAt"); - - b.ToTable("order_status_histories", null, t => - { - t.HasComment("订单状态流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.RefundRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("申请金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("ProcessedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核完成时间。"); - - b.Property("Reason") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("申请原因。"); - - b.Property("RefundNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("退款单号。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("用户提交时间。"); - - b.Property("ReviewNotes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "RefundNo") - .IsUnique(); - - b.ToTable("refund_requests", null, t => - { - t.HasComment("售后/退款申请。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("支付金额。"); - - b.Property("ChannelTransactionId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方渠道单号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Method") - .HasColumnType("integer") - .HasComment("支付方式。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付完成时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始回调内容。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("错误/备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TradeNo") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("平台交易号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("payment_records", null, t => - { - t.HasComment("支付流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRefundRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("退款金额。"); - - b.Property("ChannelRefundId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("渠道退款流水号。"); - - b.Property("CompletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("渠道返回的原始数据 JSON。"); - - b.Property("PaymentRecordId") - .HasColumnType("bigint") - .HasComment("原支付记录标识。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("退款请求时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PaymentRecordId"); - - b.ToTable("payment_refund_records", null, t => - { - t.HasComment("支付渠道退款流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.Product", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CategoryId") - .HasColumnType("bigint") - .HasComment("所属分类。"); - - b.Property("CoverImage") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("主图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("商品描述。"); - - b.Property("EnableDelivery") - .HasColumnType("boolean") - .HasComment("支持配送。"); - - b.Property("EnableDineIn") - .HasColumnType("boolean") - .HasComment("支持堂食。"); - - b.Property("EnablePickup") - .HasColumnType("boolean") - .HasComment("支持自提。"); - - b.Property("GalleryImages") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Gallery 图片逗号分隔。"); - - b.Property("IsFeatured") - .HasColumnType("boolean") - .HasComment("是否热门推荐。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("最大每单限购。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("现价。"); - - b.Property("SpuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("商品编码。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("商品状态。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("库存数量(可选)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("Subtitle") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("副标题/卖点。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("售卖单位(份/杯等)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SpuCode") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("products", null, t => - { - t.HasComment("商品(SPU)信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("MaxSelect") - .HasColumnType("integer") - .HasComment("最大选择数量。"); - - b.Property("MinSelect") - .HasColumnType("integer") - .HasComment("最小选择数量。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "Name"); - - b.ToTable("product_addon_groups", null, t => - { - t.HasComment("加料/做法分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AddonGroupId") - .HasColumnType("bigint") - .HasComment("所属加料分组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选项。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("product_addon_options", null, t => - { - t.HasComment("加料选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称,例如“辣度”“份量”。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型(单选/多选)。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("显示排序。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店,可为空表示所有门店共享。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("product_attribute_groups", null, t => - { - t.HasComment("商品规格/属性分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributeGroupId") - .HasColumnType("bigint") - .HasComment("所属规格组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选中。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AttributeGroupId", "Name") - .IsUnique(); - - b.ToTable("product_attribute_options", null, t => - { - t.HasComment("商品规格选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("分类描述。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分类名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("product_categories", null, t => - { - t.HasComment("商品分类。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductMediaAsset", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Caption") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述或标题。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MediaType") - .HasColumnType("integer") - .HasComment("媒体类型。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品标识。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Url") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("媒资链接。"); - - b.HasKey("Id"); - - b.ToTable("product_media_assets", null, t => - { - t.HasComment("商品媒资素材。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductPricingRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("条件描述(JSON),如会员等级、渠道等。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效结束时间。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("特殊价格。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("RuleType") - .HasColumnType("integer") - .HasComment("策略类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StartTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效开始时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("WeekdaysJson") - .HasColumnType("text") - .HasComment("生效星期(JSON 数组)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "RuleType"); - - b.ToTable("product_pricing_rules", null, t => - { - t.HasComment("商品价格策略,支持会员价/时段价等。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductSku", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("规格属性 JSON(记录选项 ID)。"); - - b.Property("Barcode") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("条形码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("售价。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SkuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("SKU 编码。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("可售库存。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weight") - .HasPrecision(10, 3) - .HasColumnType("numeric(10,3)") - .HasComment("重量(千克)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SkuCode") - .IsUnique(); - - b.ToTable("product_skus", null, t => - { - t.HasComment("商品 SKU,记录具体规格组合价格。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Queues.Entities.QueueTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CalledAt") - .HasColumnType("timestamp with time zone") - .HasComment("叫号时间。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedWaitMinutes") - .HasColumnType("integer") - .HasComment("预计等待分钟。"); - - b.Property("ExpiredAt") - .HasColumnType("timestamp with time zone") - .HasComment("过号时间。"); - - b.Property("PartySize") - .HasColumnType("integer") - .HasComment("就餐人数。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("获取或设置所属门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNumber") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.HasIndex("TenantId", "StoreId", "TicketNumber") - .IsUnique(); - - b.ToTable("queue_tickets", null, t => - { - t.HasComment("排队叫号。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Reservations.Entities.Reservation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CheckInCode") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("核销码/到店码。"); - - b.Property("CheckedInAt") - .HasColumnType("timestamp with time zone") - .HasComment("实际签到时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("客户姓名。"); - - b.Property("CustomerPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PeopleCount") - .HasColumnType("integer") - .HasComment("用餐人数。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("预约号。"); - - b.Property("ReservationTime") - .HasColumnType("timestamp with time zone") - .HasComment("预约时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TablePreference") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌型/标签。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ReservationNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("reservations", null, t => - { - t.HasComment("预约/预订记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.Store", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ActivatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核通过时间。"); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("Announcement") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("门店公告。"); - - b.Property("AuditStatus") - .HasColumnType("integer") - .HasComment("审核状态。"); - - b.Property("BusinessHours") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("门店营业时段描述(备用字符串)。"); - - b.Property("BusinessLicenseImageUrl") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("门店营业执照图片地址(主体不一致模式使用)。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(50) - .HasColumnType("character varying(50)") - .HasComment("门店营业执照号(主体不一致模式使用)。"); - - b.Property("BusinessStatus") - .HasColumnType("integer") - .HasComment("经营状态。"); - - b.Property("CategoryId") - .HasColumnType("bigint") - .HasComment("行业类目 ID。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("ClosureReason") - .HasColumnType("integer") - .HasComment("歇业原因。"); - - b.Property("ClosureReasonText") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("歇业原因补充说明。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("门店编码,便于扫码及外部对接。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家或地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("门店海报。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryRadiusKm") - .HasPrecision(6, 2) - .HasColumnType("numeric(6,2)") - .HasComment("默认配送半径(公里)。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("门店描述或公告。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区县信息。"); - - b.Property("ForceCloseReason") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("强制关闭原因。"); - - b.Property("ForceClosedAt") - .HasColumnType("timestamp with time zone") - .HasComment("强制关闭时间。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("LegalRepresentative") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasComment("门店法人(主体不一致模式使用)。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("高德/腾讯地图经度。"); - - b.Property("ManagerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("门店负责人姓名。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("门店名称。"); - - b.Property("OwnershipType") - .HasColumnType("integer") - .HasComment("主体类型。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("RegisteredAddress") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("门店注册地址(主体不一致模式使用)。"); - - b.Property("RejectionReason") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("审核驳回原因。"); - - b.Property("SignboardImageUrl") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("门头招牌图 URL。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("门店当前运营状态。"); - - b.Property("SubmittedAt") - .HasColumnType("timestamp with time zone") - .HasComment("提交审核时间。"); - - b.Property("SupportsDelivery") - .HasColumnType("boolean") - .HasComment("是否支持配送。"); - - b.Property("SupportsDineIn") - .HasColumnType("boolean") - .HasComment("是否支持堂食。"); - - b.Property("SupportsPickup") - .HasColumnType("boolean") - .HasComment("是否支持自提。"); - - b.Property("SupportsQueueing") - .HasColumnType("boolean") - .HasComment("支持排队叫号。"); - - b.Property("SupportsReservation") - .HasColumnType("boolean") - .HasComment("支持预约。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("门店标签(逗号分隔)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("Longitude", "Latitude") - .HasFilter("\"Longitude\" IS NOT NULL AND \"Latitude\" IS NOT NULL"); - - b.HasIndex("MerchantId", "BusinessLicenseNumber") - .IsUnique() - .HasFilter("\"BusinessLicenseNumber\" IS NOT NULL AND \"Status\" <> 3"); - - b.HasIndex("TenantId", "AuditStatus"); - - b.HasIndex("TenantId", "BusinessStatus"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.HasIndex("TenantId", "MerchantId"); - - b.HasIndex("TenantId", "OwnershipType"); - - b.ToTable("stores", null, t => - { - t.HasComment("门店信息,承载营业配置与能力。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreAuditRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("操作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("NewStatus") - .HasColumnType("integer") - .HasComment("操作后状态。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasComment("操作人名称。"); - - b.Property("PreviousStatus") - .HasColumnType("integer") - .HasComment("操作前状态。"); - - b.Property("RejectionReason") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("驳回理由文本。"); - - b.Property("RejectionReasonId") - .HasColumnType("bigint") - .HasComment("驳回理由 ID。"); - - b.Property("Remarks") - .HasMaxLength(1000) - .HasColumnType("character varying(1000)") - .HasComment("备注。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("CreatedAt"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("store_audit_records", null, t => - { - t.HasComment("门店审核记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreBusinessHour", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CapacityLimit") - .HasColumnType("integer") - .HasComment("最大接待容量或单量限制。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DayOfWeek") - .HasColumnType("integer") - .HasComment("星期几,0 表示周日。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间(本地时间)。"); - - b.Property("HourType") - .HasColumnType("integer") - .HasComment("时段类型(正常营业、休息、预约等)。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间(本地时间)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "DayOfWeek"); - - b.ToTable("store_business_hours", null, t => - { - t.HasComment("门店营业时段配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreDeliveryZone", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("EstimatedMinutes") - .HasColumnType("integer") - .HasComment("预计送达分钟。"); - - b.Property("MinimumOrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("起送价。"); - - b.Property("PolygonGeoJson") - .IsRequired() - .HasColumnType("text") - .HasComment("GeoJSON 表示的多边形范围。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ZoneName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ZoneName"); - - b.ToTable("store_delivery_zones", null, t => - { - t.HasComment("门店配送范围配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreEmployeeShift", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("排班角色。"); - - b.Property("ShiftDate") - .HasColumnType("timestamp with time zone") - .HasComment("班次日期。"); - - b.Property("StaffId") - .HasColumnType("bigint") - .HasComment("员工标识。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ShiftDate", "StaffId") - .IsUnique(); - - b.ToTable("store_employee_shifts", null, t => - { - t.HasComment("门店员工排班记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreFee", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BaseDeliveryFee") - .HasPrecision(10, 2) - .HasColumnType("numeric(10,2)") - .HasComment("基础配送费(元)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("FixedPackagingFee") - .HasPrecision(10, 2) - .HasColumnType("numeric(10,2)") - .HasComment("固定打包费(总计模式有效)。"); - - b.Property("FreeDeliveryThreshold") - .HasPrecision(10, 2) - .HasColumnType("numeric(10,2)") - .HasComment("免配送费门槛。"); - - b.Property("MinimumOrderAmount") - .HasPrecision(10, 2) - .HasColumnType("numeric(10,2)") - .HasComment("起送费(元)。"); - - b.Property("PackagingFeeMode") - .HasColumnType("integer") - .HasComment("打包费模式。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "StoreId") - .IsUnique(); - - b.ToTable("store_fees", null, t => - { - t.HasComment("门店费用配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreHoliday", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Date") - .HasColumnType("timestamp with time zone") - .HasComment("开始日期(原 Date 字段)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("结束日期(可选,用于日期范围,如春节 1.28~2.4)。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间(IsAllDay=false 时使用)。"); - - b.Property("IsAllDay") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否全天生效。true=全天;false=仅 StartTime~EndTime 时段。"); - - b.Property("IsClosed") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否闭店(兼容旧数据,新逻辑请用 OverrideType)。"); - - b.Property("OverrideType") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("覆盖类型(闭店/临时营业/调整时间)。"); - - b.Property("Reason") - .HasMaxLength(200) - .HasColumnType("character varying(200)") - .HasComment("说明内容。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间(IsAllDay=false 时使用)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Date"); - - b.ToTable("store_holidays", null, t => - { - t.HasComment("门店临时时段配置(节假日/歇业/调整营业时间)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSetting", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowDaysAhead") - .HasColumnType("integer") - .HasComment("可预约天数(含当天)。"); - - b.Property("AllowToday") - .HasColumnType("boolean") - .HasComment("是否允许当天自提。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultCutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("默认截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单笔自提最大份数。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId") - .IsUnique(); - - b.ToTable("store_pickup_settings", null, t => - { - t.HasComment("门店自提配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSlot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("容量(份数)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("当天结束时间(UTC)。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("档期名称。"); - - b.Property("ReservedCount") - .HasColumnType("integer") - .HasComment("已占用数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("当天开始时间(UTC)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weekdays") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("适用星期(逗号分隔 1-7)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("store_pickup_slots", null, t => - { - t.HasComment("门店自提档期。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreQualification", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DocumentNumber") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasComment("证照编号。"); - - b.Property("ExpiresAt") - .HasColumnType("date") - .HasComment("到期日期。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("证照文件 URL。"); - - b.Property("IssuedAt") - .HasColumnType("date") - .HasComment("签发日期。"); - - b.Property("QualificationType") - .HasColumnType("integer") - .HasComment("资质类型。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(100) - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("ExpiresAt") - .HasFilter("\"ExpiresAt\" IS NOT NULL"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("store_qualifications", null, t => - { - t.HasComment("门店资质证照。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTable", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AreaId") - .HasColumnType("bigint") - .HasComment("所在区域 ID。"); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("可容纳人数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("QrCodeUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("桌码二维码地址。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前桌台状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("桌码。"); - - b.Property("Tags") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("桌台标签(堂食、快餐等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "TableCode") - .IsUnique(); - - b.ToTable("store_tables", null, t => - { - t.HasComment("桌台信息与二维码绑定。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTableArea", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("区域描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name") - .IsUnique(); - - b.ToTable("store_table_areas", null, t => - { - t.HasComment("门店桌台区域配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.QuotaPackage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("描述。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否上架。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("配额包名称。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("价格。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型。"); - - b.Property("QuotaValue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配额数值。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("排序。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("QuotaType", "IsActive", "SortOrder"); - - b.ToTable("quota_packages", null, t => - { - t.HasComment("配额包定义(平台提供的可购买配额包)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.Tenant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("text") - .HasComment("详细地址信息。"); - - b.Property("City") - .HasColumnType("text") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("租户短编码,作为跨系统引用的唯一标识。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("主联系人邮箱。"); - - b.Property("ContactName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("主联系人姓名。"); - - b.Property("ContactPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("主联系人电话。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家/地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("品牌海报或封面图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("服务生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("服务到期时间(UTC)。"); - - b.Property("Industry") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所属行业,如餐饮、零售等。"); - - b.Property("LegalEntityName") - .HasColumnType("text") - .HasComment("法人或公司主体名称。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("LOGO 图片地址。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("租户全称或品牌名称。"); - - b.Property("OperatingMode") - .HasColumnType("integer") - .HasComment("经营模式(同一主体/不同主体)。"); - - b.Property("PrimaryOwnerUserId") - .HasColumnType("bigint") - .HasComment("系统内对应的租户所有者账号 ID。"); - - b.Property("Province") - .HasColumnType("text") - .HasComment("所在省份或州。"); - - b.Property("Remarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息,用于运营记录特殊说明。"); - - b.Property("ShortName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("对外展示的简称。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("租户当前状态,涵盖审核、启用、停用等场景。"); - - b.Property("SuspendedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次暂停服务时间。"); - - b.Property("SuspensionReason") - .HasColumnType("text") - .HasComment("暂停或终止的原因说明。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("业务标签集合(逗号分隔)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Website") - .HasColumnType("text") - .HasComment("官网或主要宣传链接。"); - - b.HasKey("Id"); - - b.HasIndex("Code") - .IsUnique(); - - b.HasIndex("ContactPhone") - .IsUnique(); - - b.ToTable("tenants", null, t => - { - t.HasComment("平台租户信息,描述租户的生命周期与基础资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementType") - .HasColumnType("integer") - .HasComment("公告类型。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("公告正文(可为 Markdown/HTML,前端自行渲染)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("失效时间(UTC),为空表示长期有效。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否启用(已弃用,迁移期保留)。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("展示优先级,数值越大越靠前。"); - - b.Property("PublishedAt") - .HasColumnType("timestamp with time zone") - .HasComment("实际发布时间(UTC)。"); - - b.Property("PublisherScope") - .HasColumnType("integer") - .HasComment("发布者范围。"); - - b.Property("PublisherUserId") - .HasColumnType("bigint") - .HasComment("发布者用户 ID(平台或租户后台账号)。"); - - b.Property("RevokedAt") - .HasColumnType("timestamp with time zone") - .HasComment("撤销时间(UTC)。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("ScheduledPublishAt") - .HasColumnType("timestamp with time zone") - .HasComment("预定发布时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("公告状态。"); - - b.Property("TargetParameters") - .HasColumnType("text") - .HasComment("目标受众参数(JSON)。"); - - b.Property("TargetType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("目标受众类型。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("公告标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("Status", "EffectiveFrom") - .HasFilter("\"TenantId\" = 0"); - - b.HasIndex("TenantId", "AnnouncementType", "IsActive"); - - b.HasIndex("TenantId", "EffectiveFrom", "EffectiveTo"); - - b.HasIndex("TenantId", "Status", "EffectiveFrom"); - - b.ToTable("tenant_announcements", null, t => - { - t.HasComment("租户公告。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncementRead", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementId") - .HasColumnType("bigint") - .HasComment("公告 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("已读时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("已读用户 ID(后台账号),为空表示租户级已读。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AnnouncementId", "UserId") - .IsUnique(); - - b.ToTable("tenant_announcement_reads", null, t => - { - t.HasComment("租户公告已读记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantBillingStatement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AmountDue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额(原始金额)。"); - - b.Property("AmountPaid") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("BillingType") - .HasColumnType("integer") - .HasComment("账单类型(订阅账单/配额包账单/手动账单/续费账单)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Currency") - .IsRequired() - .ValueGeneratedOnAdd() - .HasMaxLength(8) - .HasColumnType("character varying(8)") - .HasDefaultValue("CNY") - .HasComment("货币类型(默认 CNY)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("折扣金额。"); - - b.Property("DueDate") - .HasColumnType("timestamp with time zone") - .HasComment("到期日。"); - - b.Property("LineItemsJson") - .HasColumnType("text") - .HasComment("账单明细 JSON,记录各项费用。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息(如:人工备注、取消原因等)。"); - - b.Property("OverdueNotifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("逾期通知时间。"); - - b.Property("PeriodEnd") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期结束时间。"); - - b.Property("PeriodStart") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期开始时间。"); - - b.Property("ReminderSentAt") - .HasColumnType("timestamp with time zone") - .HasComment("提醒发送时间(续费提醒、逾期提醒等)。"); - - b.Property("StatementNo") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("账单编号,供对账查询。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前付款状态。"); - - b.Property("SubscriptionId") - .HasColumnType("bigint") - .HasComment("关联的订阅 ID(仅当 BillingType 为 Subscription 或 Renewal 时有值)。"); - - b.Property("TaxAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("税费金额。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("CreatedAt") - .HasDatabaseName("idx_billing_created_at"); - - b.HasIndex("Status", "DueDate") - .HasDatabaseName("idx_billing_status_duedate") - .HasFilter("\"Status\" IN (0, 2)"); - - b.HasIndex("TenantId", "StatementNo") - .IsUnique(); - - b.HasIndex("TenantId", "Status", "DueDate") - .HasDatabaseName("idx_billing_tenant_status_duedate"); - - b.ToTable("tenant_billing_statements", null, t => - { - t.HasComment("租户账单,用于呈现周期性收费。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantNotification", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("发布通道(站内、邮件、短信等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("通知正文。"); - - b.Property("MetadataJson") - .HasColumnType("text") - .HasComment("附加元数据 JSON。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("租户是否已阅读。"); - - b.Property("SentAt") - .HasColumnType("timestamp with time zone") - .HasComment("推送时间。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("通知重要级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("通知标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Channel", "SentAt"); - - b.ToTable("tenant_notifications", null, t => - { - t.HasComment("面向租户的站内通知或消息推送。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantPackage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("套餐描述,包含适用场景、权益等。"); - - b.Property("FeaturePoliciesJson") - .HasColumnType("text") - .HasComment("权益明细 JSON,记录自定义特性开关。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否仍启用(平台控制)。"); - - b.Property("IsAllowNewTenantPurchase") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否允许新租户购买/选择(仅影响新购)。"); - - b.Property("IsPublicVisible") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否对外可见(展示页/套餐列表可见性)。"); - - b.Property("IsRecommended") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false) - .HasComment("是否推荐展示(运营推荐标识)。"); - - b.Property("MaxAccountCount") - .HasColumnType("integer") - .HasComment("允许创建的最大账号数。"); - - b.Property("MaxDeliveryOrders") - .HasColumnType("integer") - .HasComment("每月可调用的配送单数量上限。"); - - b.Property("MaxSmsCredits") - .HasColumnType("integer") - .HasComment("每月短信额度上限。"); - - b.Property("MaxStorageGb") - .HasColumnType("integer") - .HasComment("存储容量上限(GB)。"); - - b.Property("MaxStoreCount") - .HasColumnType("integer") - .HasComment("允许的最大门店数。"); - - b.Property("MonthlyPrice") - .HasColumnType("numeric") - .HasComment("月付价格,单位:人民币元。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("套餐名称,展示给租户的简称。"); - - b.Property("PackageType") - .HasColumnType("integer") - .HasComment("套餐分类(试用、标准、旗舰等)。"); - - b.Property("PublishStatus") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("发布状态:0=草稿,1=已发布。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("展示排序,数值越小越靠前。"); - - b.PrimitiveCollection("Tags") - .IsRequired() - .HasColumnType("text[]") - .HasComment("套餐标签(用于展示与对比页)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("YearlyPrice") - .HasColumnType("numeric") - .HasComment("年付价格,单位:人民币元。"); - - b.HasKey("Id"); - - b.HasIndex("IsActive", "SortOrder"); - - b.HasIndex("PublishStatus", "IsActive", "IsPublicVisible", "IsAllowNewTenantPurchase", "SortOrder"); - - b.ToTable("tenant_packages", null, t => - { - t.HasComment("平台提供的租户套餐定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantPayment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("支付金额。"); - - b.Property("BillingStatementId") - .HasColumnType("bigint") - .HasComment("关联的账单 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Method") - .HasColumnType("integer") - .HasComment("支付方式。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付时间。"); - - b.Property("ProofUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("支付凭证 URL。"); - - b.Property("RefundReason") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("退款原因。"); - - b.Property("RefundedAt") - .HasColumnType("timestamp with time zone") - .HasComment("退款时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TransactionNo") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("交易号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("VerifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核时间。"); - - b.Property("VerifiedBy") - .HasColumnType("bigint") - .HasComment("审核人 ID(管理员)。"); - - b.HasKey("Id"); - - b.HasIndex("TransactionNo") - .HasDatabaseName("idx_payment_transaction_no") - .HasFilter("\"TransactionNo\" IS NOT NULL"); - - b.HasIndex("BillingStatementId", "PaidAt") - .HasDatabaseName("idx_payment_billing_paidat"); - - b.HasIndex("TenantId", "BillingStatementId"); - - b.ToTable("tenant_payments", null, t => - { - t.HasComment("租户支付记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaPackagePurchase", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiredAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(可选)。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("购买价格。"); - - b.Property("PurchasedAt") - .HasColumnType("timestamp with time zone") - .HasComment("购买时间。"); - - b.Property("QuotaPackageId") - .HasColumnType("bigint") - .HasComment("配额包 ID。"); - - b.Property("QuotaValue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("购买时的配额值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "QuotaPackageId", "PurchasedAt"); - - b.ToTable("tenant_quota_package_purchases", null, t => - { - t.HasComment("租户配额包购买记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaUsage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LastResetAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次重置时间。"); - - b.Property("LimitValue") - .HasColumnType("numeric") - .HasComment("当前配额上限。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型,例如门店数、短信条数等。"); - - b.Property("ResetCycle") - .HasColumnType("text") - .HasComment("配额刷新周期描述(如月、年)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedValue") - .HasColumnType("numeric") - .HasComment("已消耗的数量。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "QuotaType") - .IsUnique(); - - b.ToTable("tenant_quota_usages", null, t => - { - t.HasComment("租户配额使用情况快照。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaUsageHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChangeAmount") - .HasColumnType("numeric") - .HasComment("变更量(可选)。"); - - b.Property("ChangeReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("变更原因(可选)。"); - - b.Property("ChangeType") - .HasColumnType("integer") - .HasComment("变更类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LimitValue") - .HasColumnType("numeric") - .HasComment("限额值(记录时刻的快照)。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型。"); - - b.Property("RecordedAt") - .HasColumnType("timestamp with time zone") - .HasComment("记录时间(UTC)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedValue") - .HasColumnType("numeric") - .HasComment("已使用值(记录时刻的快照)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "RecordedAt"); - - b.HasIndex("TenantId", "QuotaType", "RecordedAt"); - - b.ToTable("tenant_quota_usage_histories", null, t => - { - t.HasComment("租户配额使用历史记录(用于追踪配额上下限与使用量的时间序列变化)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantReviewClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ClaimedAt") - .HasColumnType("timestamp with time zone") - .HasComment("领取时间(UTC)。"); - - b.Property("ClaimedBy") - .HasColumnType("bigint") - .HasComment("领取人用户 ID。"); - - b.Property("ClaimedByName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("领取人名称(展示用快照)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReleasedAt") - .HasColumnType("timestamp with time zone") - .HasComment("释放时间(UTC),未释放时为 null。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("被领取的租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("ClaimedBy"); - - b.HasIndex("TenantId") - .IsUnique() - .HasFilter("\"ReleasedAt\" IS NULL AND \"DeletedAt\" IS NULL"); - - b.ToTable("tenant_review_claims", null, t => - { - t.HasComment("租户入驻审核领取记录(防止多管理员并发审核)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscription", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AutoRenew") - .HasColumnType("boolean") - .HasComment("是否开启自动续费。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("订阅生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("订阅到期时间(UTC)。"); - - b.Property("NextBillingDate") - .HasColumnType("timestamp with time zone") - .HasComment("下一个计费时间,配合自动续费使用。"); - - b.Property("Notes") - .HasColumnType("text") - .HasComment("运营备注信息。"); - - b.Property("ScheduledPackageId") - .HasColumnType("bigint") - .HasComment("若已排期升降配,对应的新套餐 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("订阅当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TenantPackageId") - .HasColumnType("bigint") - .HasComment("当前订阅关联的套餐标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantPackageId"); - - b.ToTable("tenant_subscriptions", null, t => - { - t.HasComment("租户套餐订阅记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscriptionHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasColumnType("numeric") - .HasComment("相关费用。"); - - b.Property("ChangeType") - .HasColumnType("integer") - .HasComment("变更类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Currency") - .HasMaxLength(8) - .HasColumnType("character varying(8)") - .HasComment("币种。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("FromPackageId") - .HasColumnType("bigint") - .HasComment("原套餐 ID。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("租户标识。"); - - b.Property("TenantSubscriptionId") - .HasColumnType("bigint") - .HasComment("对应的订阅 ID。"); - - b.Property("ToPackageId") - .HasColumnType("bigint") - .HasComment("新套餐 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantSubscriptionId"); - - b.ToTable("tenant_subscription_histories", null, t => - { - t.HasComment("租户套餐订阅变更记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantVerificationProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdditionalDataJson") - .HasColumnType("text") - .HasComment("附加资料(JSON)。"); - - b.Property("BankAccountName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("开户名。"); - - b.Property("BankAccountNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("银行账号。"); - - b.Property("BankName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("银行名称。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照编号。"); - - b.Property("BusinessLicenseUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营业执照文件地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LegalPersonIdBackUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证反面。"); - - b.Property("LegalPersonIdFrontUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证正面。"); - - b.Property("LegalPersonIdNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("法人身份证号。"); - - b.Property("LegalPersonName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人姓名。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注。"); - - b.Property("ReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核时间。"); - - b.Property("ReviewedBy") - .HasColumnType("bigint") - .HasComment("审核人 ID。"); - - b.Property("ReviewedByName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("审核人姓名。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("实名状态。"); - - b.Property("SubmittedAt") - .HasColumnType("timestamp with time zone") - .HasComment("提交时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("对应的租户标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId") - .IsUnique(); - - b.ToTable("tenant_verification_profiles", null, t => - { - t.HasComment("租户实名认证资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.HasOne("TakeoutSaaS.Domain.Orders.Entities.Order", null) - .WithMany() - .HasForeignKey("OrderId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20260120090508_ExtendStoreHolidayForTemporaryHours.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20260120090508_ExtendStoreHolidayForTemporaryHours.cs deleted file mode 100644 index 2e528f1..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20260120090508_ExtendStoreHolidayForTemporaryHours.cs +++ /dev/null @@ -1,173 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - /// - public partial class ExtendStoreHolidayForTemporaryHours : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_store_holidays_TenantId_StoreId_Date", - table: "store_holidays"); - - migrationBuilder.AlterTable( - name: "store_holidays", - comment: "门店临时时段配置(节假日/歇业/调整营业时间)。", - oldComment: "门店休息日或特殊营业日。"); - - migrationBuilder.AlterColumn( - name: "Reason", - table: "store_holidays", - type: "character varying(200)", - maxLength: 200, - nullable: true, - comment: "说明内容。", - oldClrType: typeof(string), - oldType: "character varying(256)", - oldMaxLength: 256, - oldNullable: true, - oldComment: "说明内容。"); - - migrationBuilder.AlterColumn( - name: "IsClosed", - table: "store_holidays", - type: "boolean", - nullable: false, - defaultValue: true, - comment: "是否闭店(兼容旧数据,新逻辑请用 OverrideType)。", - oldClrType: typeof(bool), - oldType: "boolean", - oldComment: "是否全天闭店。"); - - migrationBuilder.AlterColumn( - name: "Date", - table: "store_holidays", - type: "timestamp with time zone", - nullable: false, - comment: "开始日期(原 Date 字段)。", - oldClrType: typeof(DateTime), - oldType: "timestamp with time zone", - oldComment: "日期。"); - - migrationBuilder.AddColumn( - name: "EndDate", - table: "store_holidays", - type: "timestamp with time zone", - nullable: true, - comment: "结束日期(可选,用于日期范围,如春节 1.28~2.4)。"); - - migrationBuilder.AddColumn( - name: "EndTime", - table: "store_holidays", - type: "interval", - nullable: true, - comment: "结束时间(IsAllDay=false 时使用)。"); - - migrationBuilder.AddColumn( - name: "IsAllDay", - table: "store_holidays", - type: "boolean", - nullable: false, - defaultValue: true, - comment: "是否全天生效。true=全天;false=仅 StartTime~EndTime 时段。"); - - migrationBuilder.AddColumn( - name: "OverrideType", - table: "store_holidays", - type: "integer", - nullable: false, - defaultValue: 0, - comment: "覆盖类型(闭店/临时营业/调整时间)。"); - - migrationBuilder.AddColumn( - name: "StartTime", - table: "store_holidays", - type: "interval", - nullable: true, - comment: "开始时间(IsAllDay=false 时使用)。"); - - migrationBuilder.CreateIndex( - name: "IX_store_holidays_TenantId_StoreId_Date", - table: "store_holidays", - columns: new[] { "TenantId", "StoreId", "Date" }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_store_holidays_TenantId_StoreId_Date", - table: "store_holidays"); - - migrationBuilder.DropColumn( - name: "EndDate", - table: "store_holidays"); - - migrationBuilder.DropColumn( - name: "EndTime", - table: "store_holidays"); - - migrationBuilder.DropColumn( - name: "IsAllDay", - table: "store_holidays"); - - migrationBuilder.DropColumn( - name: "OverrideType", - table: "store_holidays"); - - migrationBuilder.DropColumn( - name: "StartTime", - table: "store_holidays"); - - migrationBuilder.AlterTable( - name: "store_holidays", - comment: "门店休息日或特殊营业日。", - oldComment: "门店临时时段配置(节假日/歇业/调整营业时间)。"); - - migrationBuilder.AlterColumn( - name: "Reason", - table: "store_holidays", - type: "character varying(256)", - maxLength: 256, - nullable: true, - comment: "说明内容。", - oldClrType: typeof(string), - oldType: "character varying(200)", - oldMaxLength: 200, - oldNullable: true, - oldComment: "说明内容。"); - - migrationBuilder.AlterColumn( - name: "IsClosed", - table: "store_holidays", - type: "boolean", - nullable: false, - comment: "是否全天闭店。", - oldClrType: typeof(bool), - oldType: "boolean", - oldDefaultValue: true, - oldComment: "是否闭店(兼容旧数据,新逻辑请用 OverrideType)。"); - - migrationBuilder.AlterColumn( - name: "Date", - table: "store_holidays", - type: "timestamp with time zone", - nullable: false, - comment: "日期。", - oldClrType: typeof(DateTime), - oldType: "timestamp with time zone", - oldComment: "开始日期(原 Date 字段)。"); - - migrationBuilder.CreateIndex( - name: "IX_store_holidays_TenantId_StoreId_Date", - table: "store_holidays", - columns: new[] { "TenantId", "StoreId", "Date" }, - unique: true); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20260201090000_AddStoreFeeTieredPackaging.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20260201090000_AddStoreFeeTieredPackaging.cs deleted file mode 100644 index 26e6fb9..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/20260201090000_AddStoreFeeTieredPackaging.cs +++ /dev/null @@ -1,45 +0,0 @@ -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using TakeoutSaaS.Infrastructure.App.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - /// - [DbContext(typeof(TakeoutAppDbContext))] - [Migration("20260201090000_AddStoreFeeTieredPackaging")] - public partial class AddStoreFeeTieredPackaging : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "OrderPackagingFeeMode", - table: "store_fees", - type: "integer", - nullable: false, - defaultValue: 0, - comment: "订单打包费规则(按订单收费时生效)。"); - - migrationBuilder.AddColumn( - name: "PackagingFeeTiersJson", - table: "store_fees", - type: "text", - nullable: true, - comment: "阶梯打包费配置(JSON)。"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "OrderPackagingFeeMode", - table: "store_fees"); - - migrationBuilder.DropColumn( - name: "PackagingFeeTiersJson", - table: "store_fees"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251202005247_InitSnowflake_Dictionary.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251202005247_InitSnowflake_Dictionary.Designer.cs deleted file mode 100644 index 96bfd4a..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251202005247_InitSnowflake_Dictionary.Designer.cs +++ /dev/null @@ -1,210 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.Dictionary.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.DictionaryDb -{ - [DbContext(typeof(DictionaryDbContext))] - [Migration("20251202005247_InitSnowflake_Dictionary")] - partial class InitSnowflake_Dictionary - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组编码(唯一)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("描述信息。"); - - b.Property("IsEnabled") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("分组名称。"); - - b.Property("Scope") - .HasColumnType("integer") - .HasComment("分组作用域:系统/业务。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("dictionary_groups", null, t => - { - t.HasComment("参数字典分组(系统参数、业务参数)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("描述信息。"); - - b.Property("GroupId") - .HasColumnType("bigint") - .HasComment("关联分组 ID。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认项。"); - - b.Property("IsEnabled") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否启用。"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("字典项键。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(100) - .HasComment("排序值,越小越靠前。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("字典项值。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("GroupId", "Key") - .IsUnique(); - - b.ToTable("dictionary_items", null, t => - { - t.HasComment("参数字典项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryItem", b => - { - b.HasOne("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryGroup", "Group") - .WithMany("Items") - .HasForeignKey("GroupId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Group"); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryGroup", b => - { - b.Navigation("Items"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251202005247_InitSnowflake_Dictionary.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251202005247_InitSnowflake_Dictionary.cs deleted file mode 100644 index 7a1aa27..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251202005247_InitSnowflake_Dictionary.cs +++ /dev/null @@ -1,105 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.DictionaryDb -{ - /// - public partial class InitSnowflake_Dictionary : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "dictionary_groups", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - Code = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "分组编码(唯一)。"), - Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, comment: "分组名称。"), - Scope = table.Column(type: "integer", nullable: false, comment: "分组作用域:系统/业务。"), - Description = table.Column(type: "character varying(512)", maxLength: 512, nullable: true, comment: "描述信息。"), - IsEnabled = table.Column(type: "boolean", nullable: false, defaultValue: true, comment: "是否启用。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_dictionary_groups", x => x.Id); - }, - comment: "参数字典分组(系统参数、业务参数)。"); - - migrationBuilder.CreateTable( - name: "dictionary_items", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - GroupId = table.Column(type: "bigint", nullable: false, comment: "关联分组 ID。"), - Key = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "字典项键。"), - Value = table.Column(type: "character varying(256)", maxLength: 256, nullable: false, comment: "字典项值。"), - IsDefault = table.Column(type: "boolean", nullable: false, comment: "是否默认项。"), - IsEnabled = table.Column(type: "boolean", nullable: false, defaultValue: true, comment: "是否启用。"), - SortOrder = table.Column(type: "integer", nullable: false, defaultValue: 100, comment: "排序值,越小越靠前。"), - Description = table.Column(type: "character varying(512)", maxLength: 512, nullable: true, comment: "描述信息。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_dictionary_items", x => x.Id); - table.ForeignKey( - name: "FK_dictionary_items_dictionary_groups_GroupId", - column: x => x.GroupId, - principalTable: "dictionary_groups", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }, - comment: "参数字典项。"); - - migrationBuilder.CreateIndex( - name: "IX_dictionary_groups_TenantId", - table: "dictionary_groups", - column: "TenantId"); - - migrationBuilder.CreateIndex( - name: "IX_dictionary_groups_TenantId_Code", - table: "dictionary_groups", - columns: new[] { "TenantId", "Code" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_dictionary_items_GroupId_Key", - table: "dictionary_items", - columns: new[] { "GroupId", "Key" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_dictionary_items_TenantId", - table: "dictionary_items", - column: "TenantId"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "dictionary_items"); - - migrationBuilder.DropTable( - name: "dictionary_groups"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251202043204_AddSystemParametersTable.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251202043204_AddSystemParametersTable.Designer.cs deleted file mode 100644 index 8d3c8c2..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251202043204_AddSystemParametersTable.Designer.cs +++ /dev/null @@ -1,288 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.Dictionary.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.DictionaryDb -{ - [DbContext(typeof(DictionaryDbContext))] - [Migration("20251202043204_AddSystemParametersTable")] - partial class AddSystemParametersTable - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组编码(唯一)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("描述信息。"); - - b.Property("IsEnabled") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("分组名称。"); - - b.Property("Scope") - .HasColumnType("integer") - .HasComment("分组作用域:系统/业务。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("dictionary_groups", null, t => - { - t.HasComment("参数字典分组(系统参数、业务参数)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("描述信息。"); - - b.Property("GroupId") - .HasColumnType("bigint") - .HasComment("关联分组 ID。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认项。"); - - b.Property("IsEnabled") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否启用。"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("字典项键。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(100) - .HasComment("排序值,越小越靠前。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("字典项值。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("GroupId", "Key") - .IsUnique(); - - b.ToTable("dictionary_items", null, t => - { - t.HasComment("参数字典项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.SystemParameters.Entities.SystemParameter", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("描述信息。"); - - b.Property("IsEnabled") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否启用。"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("参数键,租户内唯一。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(100) - .HasComment("排序值,越小越靠前。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Value") - .IsRequired() - .HasColumnType("text") - .HasComment("参数值,支持文本或 JSON。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Key") - .IsUnique(); - - b.ToTable("system_parameters", null, t => - { - t.HasComment("系统参数实体:支持按租户维护的键值型配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryItem", b => - { - b.HasOne("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryGroup", "Group") - .WithMany("Items") - .HasForeignKey("GroupId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Group"); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryGroup", b => - { - b.Navigation("Items"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251202043204_AddSystemParametersTable.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251202043204_AddSystemParametersTable.cs deleted file mode 100644 index 27d688a..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251202043204_AddSystemParametersTable.cs +++ /dev/null @@ -1,58 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.DictionaryDb -{ - /// - public partial class AddSystemParametersTable : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "system_parameters", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - Key = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, comment: "参数键,租户内唯一。"), - Value = table.Column(type: "text", nullable: false, comment: "参数值,支持文本或 JSON。"), - Description = table.Column(type: "character varying(512)", maxLength: 512, nullable: true, comment: "描述信息。"), - SortOrder = table.Column(type: "integer", nullable: false, defaultValue: 100, comment: "排序值,越小越靠前。"), - IsEnabled = table.Column(type: "boolean", nullable: false, defaultValue: true, comment: "是否启用。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_system_parameters", x => x.Id); - }, - comment: "系统参数实体:支持按租户维护的键值型配置。"); - - migrationBuilder.CreateIndex( - name: "IX_system_parameters_TenantId", - table: "system_parameters", - column: "TenantId"); - - migrationBuilder.CreateIndex( - name: "IX_system_parameters_TenantId_Key", - table: "system_parameters", - columns: new[] { "TenantId", "Key" }, - unique: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "system_parameters"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251230044727_UpdateDictionarySchema.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251230044727_UpdateDictionarySchema.Designer.cs deleted file mode 100644 index 7a43210..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251230044727_UpdateDictionarySchema.Designer.cs +++ /dev/null @@ -1,471 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.Dictionary.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.DictionaryDb -{ - [DbContext(typeof(DictionaryDbContext))] - [Migration("20251230044727_UpdateDictionarySchema")] - partial class UpdateDictionarySchema - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.1") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowOverride") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false) - .HasComment("是否允许租户覆盖。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("描述信息。"); - - b.Property("IsEnabled") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("分组名称。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("Scope") - .HasColumnType("integer") - .HasComment("分组作用域:系统/业务。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Code") - .IsUnique() - .HasFilter("\"DeletedAt\" IS NULL"); - - b.HasIndex("TenantId", "Scope", "IsEnabled"); - - b.ToTable("dictionary_groups", null, t => - { - t.HasComment("参数字典分组(系统参数、业务参数)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryImportLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConflictMode") - .HasColumnType("integer") - .HasComment("冲突处理模式。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DictionaryGroupCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("字典分组编码。"); - - b.Property("Duration") - .HasColumnType("interval") - .HasComment("处理耗时。"); - - b.Property("ErrorDetails") - .HasColumnType("jsonb") - .HasComment("错误明细(JSON)。"); - - b.Property("FileName") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("导入文件名。"); - - b.Property("FileSize") - .HasColumnType("bigint") - .HasComment("文件大小(字节)。"); - - b.Property("Format") - .IsRequired() - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("文件格式(CSV/JSON)。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人用户标识。"); - - b.Property("ProcessedAt") - .HasColumnType("timestamp with time zone") - .HasComment("处理时间(UTC)。"); - - b.Property("SkipCount") - .HasColumnType("integer") - .HasComment("跳过数量。"); - - b.Property("SuccessCount") - .HasColumnType("integer") - .HasComment("成功导入数量。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProcessedAt"); - - b.ToTable("dictionary_import_logs", null, t => - { - t.HasComment("字典导入审计日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("描述信息。"); - - b.Property("GroupId") - .HasColumnType("bigint") - .HasComment("关联分组 ID。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认项。"); - - b.Property("IsEnabled") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否启用。"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("字典项键。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(100) - .HasComment("排序值,越小越靠前。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Value") - .IsRequired() - .HasColumnType("jsonb") - .HasComment("字典项值。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("GroupId", "IsEnabled", "SortOrder"); - - b.HasIndex("TenantId", "GroupId", "Key") - .IsUnique() - .HasFilter("\"DeletedAt\" IS NULL"); - - b.ToTable("dictionary_items", null, t => - { - t.HasComment("参数字典项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.TenantDictionaryOverride", b => - { - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("SystemDictionaryGroupId") - .HasColumnType("bigint") - .HasComment("系统字典分组 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识。"); - - b.Property("CustomSortOrder") - .IsRequired() - .HasColumnType("jsonb") - .HasComment("自定义排序映射(JSON)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("删除时间(UTC)。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识。"); - - b.PrimitiveCollection("HiddenSystemItemIds") - .IsRequired() - .HasColumnType("bigint[]") - .HasComment("隐藏的系统字典项 ID 列表。"); - - b.Property("OverrideEnabled") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false) - .HasComment("是否启用覆盖。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近更新时间(UTC)。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识。"); - - b.HasKey("TenantId", "SystemDictionaryGroupId"); - - b.HasIndex("HiddenSystemItemIds"); - - NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("HiddenSystemItemIds"), "gin"); - - b.ToTable("tenant_dictionary_overrides", null, t => - { - t.HasComment("租户字典覆盖配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.SystemParameters.Entities.SystemParameter", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("描述信息。"); - - b.Property("IsEnabled") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否启用。"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("参数键,租户内唯一。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(100) - .HasComment("排序值,越小越靠前。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Value") - .IsRequired() - .HasColumnType("text") - .HasComment("参数值,支持文本或 JSON。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Key") - .IsUnique(); - - b.ToTable("system_parameters", null, t => - { - t.HasComment("系统参数实体:支持按租户维护的键值型配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryItem", b => - { - b.HasOne("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryGroup", "Group") - .WithMany("Items") - .HasForeignKey("GroupId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Group"); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryGroup", b => - { - b.Navigation("Items"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251230044727_UpdateDictionarySchema.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251230044727_UpdateDictionarySchema.cs deleted file mode 100644 index 6045021..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251230044727_UpdateDictionarySchema.cs +++ /dev/null @@ -1,255 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.DictionaryDb -{ - /// - public partial class UpdateDictionarySchema : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_dictionary_items_GroupId_Key", - table: "dictionary_items"); - - migrationBuilder.DropIndex( - name: "IX_dictionary_groups_TenantId_Code", - table: "dictionary_groups"); - - // 使用原生 SQL 进行类型转换,确保现有数据被正确转换为 JSONB - migrationBuilder.Sql( - """ - ALTER TABLE dictionary_items - ALTER COLUMN "Value" TYPE jsonb - USING to_jsonb("Value"::text); - - COMMENT ON COLUMN dictionary_items."Value" IS '字典项值。'; - """); - - migrationBuilder.AlterColumn( - name: "Key", - table: "dictionary_items", - type: "character varying(128)", - maxLength: 128, - nullable: false, - comment: "字典项键。", - oldClrType: typeof(string), - oldType: "character varying(64)", - oldMaxLength: 64, - oldComment: "字典项键。"); - - migrationBuilder.AddColumn( - name: "RowVersion", - table: "dictionary_items", - type: "bytea", - rowVersion: true, - nullable: false, - defaultValue: new byte[0], - comment: "并发控制字段。"); - - migrationBuilder.AlterColumn( - name: "Code", - table: "dictionary_groups", - type: "character varying(64)", - maxLength: 64, - nullable: false, - oldClrType: typeof(string), - oldType: "character varying(64)", - oldMaxLength: 64, - oldComment: "分组编码(唯一)。"); - - migrationBuilder.AddColumn( - name: "AllowOverride", - table: "dictionary_groups", - type: "boolean", - nullable: false, - defaultValue: false, - comment: "是否允许租户覆盖。"); - - migrationBuilder.AddColumn( - name: "RowVersion", - table: "dictionary_groups", - type: "bytea", - rowVersion: true, - nullable: false, - defaultValue: new byte[0], - comment: "并发控制字段。"); - - migrationBuilder.CreateTable( - name: "dictionary_import_logs", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - OperatorId = table.Column(type: "bigint", nullable: false, comment: "操作人用户标识。"), - DictionaryGroupCode = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "字典分组编码。"), - FileName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false, comment: "导入文件名。"), - FileSize = table.Column(type: "bigint", nullable: false, comment: "文件大小(字节)。"), - Format = table.Column(type: "character varying(16)", maxLength: 16, nullable: false, comment: "文件格式(CSV/JSON)。"), - ConflictMode = table.Column(type: "integer", nullable: false, comment: "冲突处理模式。"), - SuccessCount = table.Column(type: "integer", nullable: false, comment: "成功导入数量。"), - SkipCount = table.Column(type: "integer", nullable: false, comment: "跳过数量。"), - ErrorDetails = table.Column(type: "jsonb", nullable: true, comment: "错误明细(JSON)。"), - ProcessedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "处理时间(UTC)。"), - Duration = table.Column(type: "interval", nullable: false, comment: "处理耗时。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_dictionary_import_logs", x => x.Id); - }, - comment: "字典导入审计日志。"); - - migrationBuilder.CreateTable( - name: "tenant_dictionary_overrides", - columns: table => new - { - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。"), - SystemDictionaryGroupId = table.Column(type: "bigint", nullable: false, comment: "系统字典分组 ID。"), - OverrideEnabled = table.Column(type: "boolean", nullable: false, defaultValue: false, comment: "是否启用覆盖。"), - HiddenSystemItemIds = table.Column(type: "bigint[]", nullable: false, comment: "隐藏的系统字典项 ID 列表。"), - CustomSortOrder = table.Column(type: "jsonb", nullable: false, comment: "自定义排序映射(JSON)。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近更新时间(UTC)。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "删除时间(UTC)。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识。") - }, - constraints: table => - { - table.PrimaryKey("PK_tenant_dictionary_overrides", x => new { x.TenantId, x.SystemDictionaryGroupId }); - }, - comment: "租户字典覆盖配置。"); - - migrationBuilder.CreateIndex( - name: "IX_dictionary_items_GroupId_IsEnabled_SortOrder", - table: "dictionary_items", - columns: new[] { "GroupId", "IsEnabled", "SortOrder" }); - - migrationBuilder.CreateIndex( - name: "IX_dictionary_items_TenantId_GroupId_Key", - table: "dictionary_items", - columns: new[] { "TenantId", "GroupId", "Key" }, - unique: true, - filter: "\"DeletedAt\" IS NULL"); - - migrationBuilder.CreateIndex( - name: "IX_dictionary_groups_TenantId_Code", - table: "dictionary_groups", - columns: new[] { "TenantId", "Code" }, - unique: true, - filter: "\"DeletedAt\" IS NULL"); - - migrationBuilder.CreateIndex( - name: "IX_dictionary_groups_TenantId_Scope_IsEnabled", - table: "dictionary_groups", - columns: new[] { "TenantId", "Scope", "IsEnabled" }); - - migrationBuilder.CreateIndex( - name: "IX_dictionary_import_logs_TenantId_ProcessedAt", - table: "dictionary_import_logs", - columns: new[] { "TenantId", "ProcessedAt" }); - - migrationBuilder.CreateIndex( - name: "IX_tenant_dictionary_overrides_HiddenSystemItemIds", - table: "tenant_dictionary_overrides", - column: "HiddenSystemItemIds") - .Annotation("Npgsql:IndexMethod", "gin"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "dictionary_import_logs"); - - migrationBuilder.DropTable( - name: "tenant_dictionary_overrides"); - - migrationBuilder.DropIndex( - name: "IX_dictionary_items_GroupId_IsEnabled_SortOrder", - table: "dictionary_items"); - - migrationBuilder.DropIndex( - name: "IX_dictionary_items_TenantId_GroupId_Key", - table: "dictionary_items"); - - migrationBuilder.DropIndex( - name: "IX_dictionary_groups_TenantId_Code", - table: "dictionary_groups"); - - migrationBuilder.DropIndex( - name: "IX_dictionary_groups_TenantId_Scope_IsEnabled", - table: "dictionary_groups"); - - migrationBuilder.DropColumn( - name: "RowVersion", - table: "dictionary_items"); - - migrationBuilder.DropColumn( - name: "AllowOverride", - table: "dictionary_groups"); - - migrationBuilder.DropColumn( - name: "RowVersion", - table: "dictionary_groups"); - - migrationBuilder.AlterColumn( - name: "Value", - table: "dictionary_items", - type: "character varying(256)", - maxLength: 256, - nullable: false, - comment: "字典项值。", - oldClrType: typeof(string), - oldType: "jsonb", - oldComment: "字典项值。"); - - migrationBuilder.AlterColumn( - name: "Key", - table: "dictionary_items", - type: "character varying(64)", - maxLength: 64, - nullable: false, - comment: "字典项键。", - oldClrType: typeof(string), - oldType: "character varying(128)", - oldMaxLength: 128, - oldComment: "字典项键。"); - - migrationBuilder.AlterColumn( - name: "Code", - table: "dictionary_groups", - type: "character varying(64)", - maxLength: 64, - nullable: false, - comment: "分组编码(唯一)。", - oldClrType: typeof(string), - oldType: "character varying(64)", - oldMaxLength: 64); - - migrationBuilder.CreateIndex( - name: "IX_dictionary_items_GroupId_Key", - table: "dictionary_items", - columns: new[] { "GroupId", "Key" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_dictionary_groups_TenantId_Code", - table: "dictionary_groups", - columns: new[] { "TenantId", "Code" }, - unique: true); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251230140335_AddCacheInvalidationLogs.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251230140335_AddCacheInvalidationLogs.Designer.cs deleted file mode 100644 index 50fd6bb..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251230140335_AddCacheInvalidationLogs.Designer.cs +++ /dev/null @@ -1,544 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.Dictionary.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.DictionaryDb -{ - [DbContext(typeof(DictionaryDbContext))] - [Migration("20251230140335_AddCacheInvalidationLogs")] - partial class AddCacheInvalidationLogs - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.1") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.CacheInvalidationLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffectedCacheKeyCount") - .HasColumnType("integer") - .HasComment("影响的缓存键数量。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DictionaryCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("字典编码。"); - - b.Property("Operation") - .HasColumnType("integer") - .HasComment("操作类型。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人用户标识。"); - - b.Property("Scope") - .HasColumnType("integer") - .HasComment("字典作用域。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Timestamp") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间(UTC)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Timestamp"); - - b.ToTable("dictionary_cache_invalidation_logs", null, t => - { - t.HasComment("字典缓存失效日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowOverride") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false) - .HasComment("是否允许租户覆盖。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("描述信息。"); - - b.Property("IsEnabled") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("分组名称。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("Scope") - .HasColumnType("integer") - .HasComment("分组作用域:系统/业务。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Code") - .IsUnique() - .HasFilter("\"DeletedAt\" IS NULL"); - - b.HasIndex("TenantId", "Scope", "IsEnabled"); - - b.ToTable("dictionary_groups", null, t => - { - t.HasComment("参数字典分组(系统参数、业务参数)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryImportLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConflictMode") - .HasColumnType("integer") - .HasComment("冲突处理模式。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DictionaryGroupCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("字典分组编码。"); - - b.Property("Duration") - .HasColumnType("interval") - .HasComment("处理耗时。"); - - b.Property("ErrorDetails") - .HasColumnType("jsonb") - .HasComment("错误明细(JSON)。"); - - b.Property("FileName") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("导入文件名。"); - - b.Property("FileSize") - .HasColumnType("bigint") - .HasComment("文件大小(字节)。"); - - b.Property("Format") - .IsRequired() - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("文件格式(CSV/JSON)。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人用户标识。"); - - b.Property("ProcessedAt") - .HasColumnType("timestamp with time zone") - .HasComment("处理时间(UTC)。"); - - b.Property("SkipCount") - .HasColumnType("integer") - .HasComment("跳过数量。"); - - b.Property("SuccessCount") - .HasColumnType("integer") - .HasComment("成功导入数量。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProcessedAt"); - - b.ToTable("dictionary_import_logs", null, t => - { - t.HasComment("字典导入审计日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("描述信息。"); - - b.Property("GroupId") - .HasColumnType("bigint") - .HasComment("关联分组 ID。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认项。"); - - b.Property("IsEnabled") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否启用。"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("字典项键。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(100) - .HasComment("排序值,越小越靠前。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Value") - .IsRequired() - .HasColumnType("jsonb") - .HasComment("字典项值。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("GroupId", "IsEnabled", "SortOrder"); - - b.HasIndex("TenantId", "GroupId", "Key") - .IsUnique() - .HasFilter("\"DeletedAt\" IS NULL"); - - b.ToTable("dictionary_items", null, t => - { - t.HasComment("参数字典项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.TenantDictionaryOverride", b => - { - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("SystemDictionaryGroupId") - .HasColumnType("bigint") - .HasComment("系统字典分组 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识。"); - - b.Property("CustomSortOrder") - .IsRequired() - .HasColumnType("jsonb") - .HasComment("自定义排序映射(JSON)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("删除时间(UTC)。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识。"); - - b.PrimitiveCollection("HiddenSystemItemIds") - .IsRequired() - .HasColumnType("bigint[]") - .HasComment("隐藏的系统字典项 ID 列表。"); - - b.Property("OverrideEnabled") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false) - .HasComment("是否启用覆盖。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近更新时间(UTC)。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识。"); - - b.HasKey("TenantId", "SystemDictionaryGroupId"); - - b.HasIndex("HiddenSystemItemIds"); - - NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("HiddenSystemItemIds"), "gin"); - - b.ToTable("tenant_dictionary_overrides", null, t => - { - t.HasComment("租户字典覆盖配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.SystemParameters.Entities.SystemParameter", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("描述信息。"); - - b.Property("IsEnabled") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否启用。"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("参数键,租户内唯一。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(100) - .HasComment("排序值,越小越靠前。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Value") - .IsRequired() - .HasColumnType("text") - .HasComment("参数值,支持文本或 JSON。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Key") - .IsUnique(); - - b.ToTable("system_parameters", null, t => - { - t.HasComment("系统参数实体:支持按租户维护的键值型配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryItem", b => - { - b.HasOne("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryGroup", "Group") - .WithMany("Items") - .HasForeignKey("GroupId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Group"); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryGroup", b => - { - b.Navigation("Items"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251230140335_AddCacheInvalidationLogs.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251230140335_AddCacheInvalidationLogs.cs deleted file mode 100644 index cafa46c..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251230140335_AddCacheInvalidationLogs.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.DictionaryDb -{ - /// - public partial class AddCacheInvalidationLogs : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "dictionary_cache_invalidation_logs", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - Timestamp = table.Column(type: "timestamp with time zone", nullable: false, comment: "发生时间(UTC)。"), - DictionaryCode = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "字典编码。"), - Scope = table.Column(type: "integer", nullable: false, comment: "字典作用域。"), - AffectedCacheKeyCount = table.Column(type: "integer", nullable: false, comment: "影响的缓存键数量。"), - OperatorId = table.Column(type: "bigint", nullable: false, comment: "操作人用户标识。"), - Operation = table.Column(type: "integer", nullable: false, comment: "操作类型。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_dictionary_cache_invalidation_logs", x => x.Id); - }, - comment: "字典缓存失效日志。"); - - migrationBuilder.CreateIndex( - name: "IX_dictionary_cache_invalidation_logs_TenantId_Timestamp", - table: "dictionary_cache_invalidation_logs", - columns: new[] { "TenantId", "Timestamp" }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "dictionary_cache_invalidation_logs"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251230170000_AddDictionaryRowVersionTriggers.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251230170000_AddDictionaryRowVersionTriggers.cs deleted file mode 100644 index 076fc33..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251230170000_AddDictionaryRowVersionTriggers.cs +++ /dev/null @@ -1,77 +0,0 @@ -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using TakeoutSaaS.Infrastructure.Dictionary.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.DictionaryDb -{ - /// - /// 为字典表添加 RowVersion 自动生成触发器。 - /// - [DbContext(typeof(DictionaryDbContext))] - [Migration("20251230170000_AddDictionaryRowVersionTriggers")] - public partial class AddDictionaryRowVersionTriggers : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - // 1. 创建通用的 RowVersion 生成函数 - migrationBuilder.Sql( - """ - CREATE OR REPLACE FUNCTION public.set_dictionary_row_version() - RETURNS trigger AS $$ - BEGIN - NEW."RowVersion" = decode(md5(random()::text || clock_timestamp()::text), 'hex'); - RETURN NEW; - END; - $$ LANGUAGE plpgsql; - """); - - // 2. 为 dictionary_groups 表创建触发器 - migrationBuilder.Sql( - """ - DROP TRIGGER IF EXISTS trg_dictionary_groups_row_version ON dictionary_groups; - CREATE TRIGGER trg_dictionary_groups_row_version - BEFORE INSERT OR UPDATE ON dictionary_groups - FOR EACH ROW EXECUTE FUNCTION public.set_dictionary_row_version(); - """); - - // 3. 为 dictionary_items 表创建触发器 - migrationBuilder.Sql( - """ - DROP TRIGGER IF EXISTS trg_dictionary_items_row_version ON dictionary_items; - CREATE TRIGGER trg_dictionary_items_row_version - BEFORE INSERT OR UPDATE ON dictionary_items - FOR EACH ROW EXECUTE FUNCTION public.set_dictionary_row_version(); - """); - - // 4. 回填现有 dictionary_groups 数据的 RowVersion - migrationBuilder.Sql( - """ - UPDATE dictionary_groups - SET "RowVersion" = decode(md5(random()::text || clock_timestamp()::text), 'hex') - WHERE "RowVersion" IS NULL OR octet_length("RowVersion") = 0; - """); - - // 5. 回填现有 dictionary_items 数据的 RowVersion - migrationBuilder.Sql( - """ - UPDATE dictionary_items - SET "RowVersion" = decode(md5(random()::text || clock_timestamp()::text), 'hex') - WHERE "RowVersion" IS NULL OR octet_length("RowVersion") = 0; - """); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.Sql( - """ - DROP TRIGGER IF EXISTS trg_dictionary_groups_row_version ON dictionary_groups; - DROP TRIGGER IF EXISTS trg_dictionary_items_row_version ON dictionary_items; - DROP FUNCTION IF EXISTS public.set_dictionary_row_version(); - """); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251230232516_AddDictionaryLabelOverrides.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251230232516_AddDictionaryLabelOverrides.Designer.cs deleted file mode 100644 index 621bacd..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251230232516_AddDictionaryLabelOverrides.Designer.cs +++ /dev/null @@ -1,633 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.Dictionary.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.DictionaryDb -{ - [DbContext(typeof(DictionaryDbContext))] - [Migration("20251230232516_AddDictionaryLabelOverrides")] - partial class AddDictionaryLabelOverrides - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.1") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.CacheInvalidationLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffectedCacheKeyCount") - .HasColumnType("integer") - .HasComment("影响的缓存键数量。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DictionaryCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("字典编码。"); - - b.Property("Operation") - .HasColumnType("integer") - .HasComment("操作类型。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人用户标识。"); - - b.Property("Scope") - .HasColumnType("integer") - .HasComment("字典作用域。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Timestamp") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间(UTC)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Timestamp"); - - b.ToTable("dictionary_cache_invalidation_logs", null, t => - { - t.HasComment("字典缓存失效日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowOverride") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false) - .HasComment("是否允许租户覆盖。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("描述信息。"); - - b.Property("IsEnabled") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("分组名称。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("Scope") - .HasColumnType("integer") - .HasComment("分组作用域:系统/业务。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Code") - .IsUnique() - .HasFilter("\"DeletedAt\" IS NULL"); - - b.HasIndex("TenantId", "Scope", "IsEnabled"); - - b.ToTable("dictionary_groups", null, t => - { - t.HasComment("参数字典分组(系统参数、业务参数)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryImportLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConflictMode") - .HasColumnType("integer") - .HasComment("冲突处理模式。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DictionaryGroupCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("字典分组编码。"); - - b.Property("Duration") - .HasColumnType("interval") - .HasComment("处理耗时。"); - - b.Property("ErrorDetails") - .HasColumnType("jsonb") - .HasComment("错误明细(JSON)。"); - - b.Property("FileName") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("导入文件名。"); - - b.Property("FileSize") - .HasColumnType("bigint") - .HasComment("文件大小(字节)。"); - - b.Property("Format") - .IsRequired() - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("文件格式(CSV/JSON)。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人用户标识。"); - - b.Property("ProcessedAt") - .HasColumnType("timestamp with time zone") - .HasComment("处理时间(UTC)。"); - - b.Property("SkipCount") - .HasColumnType("integer") - .HasComment("跳过数量。"); - - b.Property("SuccessCount") - .HasColumnType("integer") - .HasComment("成功导入数量。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProcessedAt"); - - b.ToTable("dictionary_import_logs", null, t => - { - t.HasComment("字典导入审计日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("描述信息。"); - - b.Property("GroupId") - .HasColumnType("bigint") - .HasComment("关联分组 ID。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认项。"); - - b.Property("IsEnabled") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否启用。"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("字典项键。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(100) - .HasComment("排序值,越小越靠前。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Value") - .IsRequired() - .HasColumnType("jsonb") - .HasComment("字典项值。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("GroupId", "IsEnabled", "SortOrder"); - - b.HasIndex("TenantId", "GroupId", "Key") - .IsUnique() - .HasFilter("\"DeletedAt\" IS NULL"); - - b.ToTable("dictionary_items", null, t => - { - t.HasComment("参数字典项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryLabelOverride", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("删除时间(UTC)。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识。"); - - b.Property("DictionaryItemId") - .HasColumnType("bigint") - .HasComment("被覆盖的字典项 ID。"); - - b.Property("OriginalValue") - .IsRequired() - .HasColumnType("jsonb") - .HasComment("原始显示值(JSON 格式,多语言)。"); - - b.Property("OverrideType") - .HasColumnType("integer") - .HasComment("覆盖类型。"); - - b.Property("OverrideValue") - .IsRequired() - .HasColumnType("jsonb") - .HasComment("覆盖后的显示值(JSON 格式,多语言)。"); - - b.Property("Reason") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("覆盖原因/备注。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID(覆盖目标租户)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近更新时间(UTC)。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("DictionaryItemId"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "DictionaryItemId") - .IsUnique() - .HasFilter("\"DeletedAt\" IS NULL"); - - b.HasIndex("TenantId", "OverrideType"); - - b.ToTable("dictionary_label_overrides", null, t => - { - t.HasComment("字典标签覆盖配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.TenantDictionaryOverride", b => - { - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("SystemDictionaryGroupId") - .HasColumnType("bigint") - .HasComment("系统字典分组 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识。"); - - b.Property("CustomSortOrder") - .IsRequired() - .HasColumnType("jsonb") - .HasComment("自定义排序映射(JSON)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("删除时间(UTC)。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识。"); - - b.PrimitiveCollection("HiddenSystemItemIds") - .IsRequired() - .HasColumnType("bigint[]") - .HasComment("隐藏的系统字典项 ID 列表。"); - - b.Property("OverrideEnabled") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false) - .HasComment("是否启用覆盖。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近更新时间(UTC)。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识。"); - - b.HasKey("TenantId", "SystemDictionaryGroupId"); - - b.HasIndex("HiddenSystemItemIds"); - - NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("HiddenSystemItemIds"), "gin"); - - b.ToTable("tenant_dictionary_overrides", null, t => - { - t.HasComment("租户字典覆盖配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.SystemParameters.Entities.SystemParameter", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("描述信息。"); - - b.Property("IsEnabled") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否启用。"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("参数键,租户内唯一。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(100) - .HasComment("排序值,越小越靠前。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Value") - .IsRequired() - .HasColumnType("text") - .HasComment("参数值,支持文本或 JSON。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Key") - .IsUnique(); - - b.ToTable("system_parameters", null, t => - { - t.HasComment("系统参数实体:支持按租户维护的键值型配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryItem", b => - { - b.HasOne("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryGroup", "Group") - .WithMany("Items") - .HasForeignKey("GroupId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Group"); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryLabelOverride", b => - { - b.HasOne("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryItem", "DictionaryItem") - .WithMany() - .HasForeignKey("DictionaryItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("DictionaryItem"); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryGroup", b => - { - b.Navigation("Items"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251230232516_AddDictionaryLabelOverrides.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251230232516_AddDictionaryLabelOverrides.cs deleted file mode 100644 index 51687b4..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/20251230232516_AddDictionaryLabelOverrides.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.DictionaryDb -{ - /// - public partial class AddDictionaryLabelOverrides : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "dictionary_label_overrides", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID(覆盖目标租户)。"), - DictionaryItemId = table.Column(type: "bigint", nullable: false, comment: "被覆盖的字典项 ID。"), - OriginalValue = table.Column(type: "jsonb", nullable: false, comment: "原始显示值(JSON 格式,多语言)。"), - OverrideValue = table.Column(type: "jsonb", nullable: false, comment: "覆盖后的显示值(JSON 格式,多语言)。"), - OverrideType = table.Column(type: "integer", nullable: false, comment: "覆盖类型。"), - Reason = table.Column(type: "character varying(512)", maxLength: 512, nullable: true, comment: "覆盖原因/备注。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近更新时间(UTC)。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "删除时间(UTC)。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识。") - }, - constraints: table => - { - table.PrimaryKey("PK_dictionary_label_overrides", x => x.Id); - table.ForeignKey( - name: "FK_dictionary_label_overrides_dictionary_items_DictionaryItemId", - column: x => x.DictionaryItemId, - principalTable: "dictionary_items", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }, - comment: "字典标签覆盖配置。"); - - migrationBuilder.CreateIndex( - name: "IX_dictionary_label_overrides_DictionaryItemId", - table: "dictionary_label_overrides", - column: "DictionaryItemId"); - - migrationBuilder.CreateIndex( - name: "IX_dictionary_label_overrides_TenantId", - table: "dictionary_label_overrides", - column: "TenantId"); - - migrationBuilder.CreateIndex( - name: "IX_dictionary_label_overrides_TenantId_DictionaryItemId", - table: "dictionary_label_overrides", - columns: new[] { "TenantId", "DictionaryItemId" }, - unique: true, - filter: "\"DeletedAt\" IS NULL"); - - migrationBuilder.CreateIndex( - name: "IX_dictionary_label_overrides_TenantId_OverrideType", - table: "dictionary_label_overrides", - columns: new[] { "TenantId", "OverrideType" }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "dictionary_label_overrides"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/DictionaryDbContextModelSnapshot.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/DictionaryDbContextModelSnapshot.cs deleted file mode 100644 index bda7474..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/DictionaryDb/DictionaryDbContextModelSnapshot.cs +++ /dev/null @@ -1,630 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.Dictionary.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.DictionaryDb -{ - [DbContext(typeof(DictionaryDbContext))] - partial class DictionaryDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.1") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.CacheInvalidationLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffectedCacheKeyCount") - .HasColumnType("integer") - .HasComment("影响的缓存键数量。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DictionaryCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("字典编码。"); - - b.Property("Operation") - .HasColumnType("integer") - .HasComment("操作类型。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人用户标识。"); - - b.Property("Scope") - .HasColumnType("integer") - .HasComment("字典作用域。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Timestamp") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间(UTC)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Timestamp"); - - b.ToTable("dictionary_cache_invalidation_logs", null, t => - { - t.HasComment("字典缓存失效日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowOverride") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false) - .HasComment("是否允许租户覆盖。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("描述信息。"); - - b.Property("IsEnabled") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("分组名称。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("Scope") - .HasColumnType("integer") - .HasComment("分组作用域:系统/业务。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Code") - .IsUnique() - .HasFilter("\"DeletedAt\" IS NULL"); - - b.HasIndex("TenantId", "Scope", "IsEnabled"); - - b.ToTable("dictionary_groups", null, t => - { - t.HasComment("参数字典分组(系统参数、业务参数)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryImportLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConflictMode") - .HasColumnType("integer") - .HasComment("冲突处理模式。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DictionaryGroupCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("字典分组编码。"); - - b.Property("Duration") - .HasColumnType("interval") - .HasComment("处理耗时。"); - - b.Property("ErrorDetails") - .HasColumnType("jsonb") - .HasComment("错误明细(JSON)。"); - - b.Property("FileName") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("导入文件名。"); - - b.Property("FileSize") - .HasColumnType("bigint") - .HasComment("文件大小(字节)。"); - - b.Property("Format") - .IsRequired() - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("文件格式(CSV/JSON)。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人用户标识。"); - - b.Property("ProcessedAt") - .HasColumnType("timestamp with time zone") - .HasComment("处理时间(UTC)。"); - - b.Property("SkipCount") - .HasColumnType("integer") - .HasComment("跳过数量。"); - - b.Property("SuccessCount") - .HasColumnType("integer") - .HasComment("成功导入数量。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProcessedAt"); - - b.ToTable("dictionary_import_logs", null, t => - { - t.HasComment("字典导入审计日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("描述信息。"); - - b.Property("GroupId") - .HasColumnType("bigint") - .HasComment("关联分组 ID。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认项。"); - - b.Property("IsEnabled") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否启用。"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("字典项键。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(100) - .HasComment("排序值,越小越靠前。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Value") - .IsRequired() - .HasColumnType("jsonb") - .HasComment("字典项值。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("GroupId", "IsEnabled", "SortOrder"); - - b.HasIndex("TenantId", "GroupId", "Key") - .IsUnique() - .HasFilter("\"DeletedAt\" IS NULL"); - - b.ToTable("dictionary_items", null, t => - { - t.HasComment("参数字典项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryLabelOverride", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("删除时间(UTC)。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识。"); - - b.Property("DictionaryItemId") - .HasColumnType("bigint") - .HasComment("被覆盖的字典项 ID。"); - - b.Property("OriginalValue") - .IsRequired() - .HasColumnType("jsonb") - .HasComment("原始显示值(JSON 格式,多语言)。"); - - b.Property("OverrideType") - .HasColumnType("integer") - .HasComment("覆盖类型。"); - - b.Property("OverrideValue") - .IsRequired() - .HasColumnType("jsonb") - .HasComment("覆盖后的显示值(JSON 格式,多语言)。"); - - b.Property("Reason") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("覆盖原因/备注。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID(覆盖目标租户)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近更新时间(UTC)。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("DictionaryItemId"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "DictionaryItemId") - .IsUnique() - .HasFilter("\"DeletedAt\" IS NULL"); - - b.HasIndex("TenantId", "OverrideType"); - - b.ToTable("dictionary_label_overrides", null, t => - { - t.HasComment("字典标签覆盖配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.TenantDictionaryOverride", b => - { - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("SystemDictionaryGroupId") - .HasColumnType("bigint") - .HasComment("系统字典分组 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识。"); - - b.Property("CustomSortOrder") - .IsRequired() - .HasColumnType("jsonb") - .HasComment("自定义排序映射(JSON)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("删除时间(UTC)。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识。"); - - b.PrimitiveCollection("HiddenSystemItemIds") - .IsRequired() - .HasColumnType("bigint[]") - .HasComment("隐藏的系统字典项 ID 列表。"); - - b.Property("OverrideEnabled") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false) - .HasComment("是否启用覆盖。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近更新时间(UTC)。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识。"); - - b.HasKey("TenantId", "SystemDictionaryGroupId"); - - b.HasIndex("HiddenSystemItemIds"); - - NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("HiddenSystemItemIds"), "gin"); - - b.ToTable("tenant_dictionary_overrides", null, t => - { - t.HasComment("租户字典覆盖配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.SystemParameters.Entities.SystemParameter", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("描述信息。"); - - b.Property("IsEnabled") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否启用。"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("参数键,租户内唯一。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(100) - .HasComment("排序值,越小越靠前。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Value") - .IsRequired() - .HasColumnType("text") - .HasComment("参数值,支持文本或 JSON。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Key") - .IsUnique(); - - b.ToTable("system_parameters", null, t => - { - t.HasComment("系统参数实体:支持按租户维护的键值型配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryItem", b => - { - b.HasOne("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryGroup", "Group") - .WithMany("Items") - .HasForeignKey("GroupId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Group"); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryLabelOverride", b => - { - b.HasOne("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryItem", "DictionaryItem") - .WithMany() - .HasForeignKey("DictionaryItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("DictionaryItem"); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryGroup", b => - { - b.Navigation("Items"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251202005226_InitSnowflake_Identity.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251202005226_InitSnowflake_Identity.Designer.cs deleted file mode 100644 index 87e37a5..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251202005226_InitSnowflake_Identity.Designer.cs +++ /dev/null @@ -1,189 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.Identity.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.IdentityDb -{ - [DbContext(typeof(IdentityDbContext))] - [Migration("20251202005226_InitSnowflake_Identity")] - partial class InitSnowflake_Identity - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.IdentityUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Account") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("登录账号。"); - - b.Property("Avatar") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("展示名称。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户(平台管理员为空)。"); - - b.Property("PasswordHash") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("密码哈希。"); - - b.Property("Permissions") - .IsRequired() - .HasColumnType("text") - .HasComment("权限集合。"); - - b.Property("Roles") - .IsRequired() - .HasColumnType("text") - .HasComment("角色集合。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Account") - .IsUnique(); - - b.ToTable("identity_users", null, t => - { - t.HasComment("管理后台账户实体(平台管理员、租户管理员或商户员工)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.MiniUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Avatar") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Nickname") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称。"); - - b.Property("OpenId") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("微信 OpenId。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UnionId") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("微信 UnionId,可能为空。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "OpenId") - .IsUnique(); - - b.ToTable("mini_users", null, t => - { - t.HasComment("小程序用户实体。"); - }); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251202005226_InitSnowflake_Identity.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251202005226_InitSnowflake_Identity.cs deleted file mode 100644 index 4893332..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251202005226_InitSnowflake_Identity.cs +++ /dev/null @@ -1,98 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.IdentityDb -{ - /// - public partial class InitSnowflake_Identity : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "identity_users", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - Account = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "登录账号。"), - DisplayName = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "展示名称。"), - PasswordHash = table.Column(type: "character varying(256)", maxLength: 256, nullable: false, comment: "密码哈希。"), - MerchantId = table.Column(type: "bigint", nullable: true, comment: "所属商户(平台管理员为空)。"), - Roles = table.Column(type: "text", nullable: false, comment: "角色集合。"), - Permissions = table.Column(type: "text", nullable: false, comment: "权限集合。"), - Avatar = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "头像地址。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_identity_users", x => x.Id); - }, - comment: "管理后台账户实体(平台管理员、租户管理员或商户员工)。"); - - migrationBuilder.CreateTable( - name: "mini_users", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - OpenId = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, comment: "微信 OpenId。"), - UnionId = table.Column(type: "character varying(128)", maxLength: 128, nullable: true, comment: "微信 UnionId,可能为空。"), - Nickname = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "昵称。"), - Avatar = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "头像地址。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_mini_users", x => x.Id); - }, - comment: "小程序用户实体。"); - - migrationBuilder.CreateIndex( - name: "IX_identity_users_TenantId", - table: "identity_users", - column: "TenantId"); - - migrationBuilder.CreateIndex( - name: "IX_identity_users_TenantId_Account", - table: "identity_users", - columns: new[] { "TenantId", "Account" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_mini_users_TenantId", - table: "mini_users", - column: "TenantId"); - - migrationBuilder.CreateIndex( - name: "IX_mini_users_TenantId_OpenId", - table: "mini_users", - columns: new[] { "TenantId", "OpenId" }, - unique: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "identity_users"); - - migrationBuilder.DropTable( - name: "mini_users"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251202084523_AddRbacModel.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251202084523_AddRbacModel.Designer.cs deleted file mode 100644 index aeeb414..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251202084523_AddRbacModel.Designer.cs +++ /dev/null @@ -1,429 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.Identity.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.IdentityDb -{ - [DbContext(typeof(IdentityDbContext))] - [Migration("20251202084523_AddRbacModel")] - partial class AddRbacModel - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.IdentityUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Account") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("登录账号。"); - - b.Property("Avatar") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("展示名称。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户(平台管理员为空)。"); - - b.Property("PasswordHash") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("密码哈希。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Account") - .IsUnique(); - - b.ToTable("identity_users", null, t => - { - t.HasComment("管理后台账户实体(平台管理员、租户管理员或商户员工)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.MiniUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Avatar") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Nickname") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称。"); - - b.Property("OpenId") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("微信 OpenId。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UnionId") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("微信 UnionId,可能为空。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "OpenId") - .IsUnique(); - - b.ToTable("mini_users", null, t => - { - t.HasComment("小程序用户实体。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("权限编码(租户内唯一)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("权限名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("permissions", null, t => - { - t.HasComment("权限定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.Role", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("角色编码(租户内唯一)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("角色名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("roles", null, t => - { - t.HasComment("角色定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RolePermission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PermissionId") - .HasColumnType("bigint") - .HasComment("权限 ID。"); - - b.Property("RoleId") - .HasColumnType("bigint") - .HasComment("角色 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "RoleId", "PermissionId") - .IsUnique(); - - b.ToTable("role_permissions", null, t => - { - t.HasComment("角色-权限关系。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.UserRole", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("RoleId") - .HasColumnType("bigint") - .HasComment("角色 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "UserId", "RoleId") - .IsUnique(); - - b.ToTable("user_roles", null, t => - { - t.HasComment("用户-角色关系。"); - }); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251202084523_AddRbacModel.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251202084523_AddRbacModel.cs deleted file mode 100644 index 42a404e..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251202084523_AddRbacModel.cs +++ /dev/null @@ -1,189 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.IdentityDb -{ - /// - public partial class AddRbacModel : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "Permissions", - table: "identity_users"); - - migrationBuilder.DropColumn( - name: "Roles", - table: "identity_users"); - - migrationBuilder.CreateTable( - name: "permissions", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "权限名称。"), - Code = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, comment: "权限编码(租户内唯一)。"), - Description = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "描述。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_permissions", x => x.Id); - }, - comment: "权限定义。"); - - migrationBuilder.CreateTable( - name: "role_permissions", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - RoleId = table.Column(type: "bigint", nullable: false, comment: "角色 ID。"), - PermissionId = table.Column(type: "bigint", nullable: false, comment: "权限 ID。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_role_permissions", x => x.Id); - }, - comment: "角色-权限关系。"); - - migrationBuilder.CreateTable( - name: "roles", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "角色名称。"), - Code = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "角色编码(租户内唯一)。"), - Description = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "描述。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_roles", x => x.Id); - }, - comment: "角色定义。"); - - migrationBuilder.CreateTable( - name: "user_roles", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - UserId = table.Column(type: "bigint", nullable: false, comment: "用户 ID。"), - RoleId = table.Column(type: "bigint", nullable: false, comment: "角色 ID。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_user_roles", x => x.Id); - }, - comment: "用户-角色关系。"); - - migrationBuilder.CreateIndex( - name: "IX_permissions_TenantId", - table: "permissions", - column: "TenantId"); - - migrationBuilder.CreateIndex( - name: "IX_permissions_TenantId_Code", - table: "permissions", - columns: new[] { "TenantId", "Code" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_role_permissions_TenantId", - table: "role_permissions", - column: "TenantId"); - - migrationBuilder.CreateIndex( - name: "IX_role_permissions_TenantId_RoleId_PermissionId", - table: "role_permissions", - columns: new[] { "TenantId", "RoleId", "PermissionId" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_roles_TenantId", - table: "roles", - column: "TenantId"); - - migrationBuilder.CreateIndex( - name: "IX_roles_TenantId_Code", - table: "roles", - columns: new[] { "TenantId", "Code" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_user_roles_TenantId", - table: "user_roles", - column: "TenantId"); - - migrationBuilder.CreateIndex( - name: "IX_user_roles_TenantId_UserId_RoleId", - table: "user_roles", - columns: new[] { "TenantId", "UserId", "RoleId" }, - unique: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "permissions"); - - migrationBuilder.DropTable( - name: "role_permissions"); - - migrationBuilder.DropTable( - name: "roles"); - - migrationBuilder.DropTable( - name: "user_roles"); - - migrationBuilder.AddColumn( - name: "Permissions", - table: "identity_users", - type: "text", - nullable: false, - defaultValue: "", - comment: "权限集合。"); - - migrationBuilder.AddColumn( - name: "Roles", - table: "identity_users", - type: "text", - nullable: false, - defaultValue: "", - comment: "角色集合。"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251204070039_AddRoleTemplateTables.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251204070039_AddRoleTemplateTables.Designer.cs deleted file mode 100644 index d7309a7..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251204070039_AddRoleTemplateTables.Designer.cs +++ /dev/null @@ -1,548 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.Identity.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.IdentityDb -{ - [DbContext(typeof(IdentityDbContext))] - [Migration("20251204070039_AddRoleTemplateTables")] - partial class AddRoleTemplateTables - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.IdentityUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Account") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("登录账号。"); - - b.Property("Avatar") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("展示名称。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户(平台管理员为空)。"); - - b.Property("PasswordHash") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("密码哈希。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Account") - .IsUnique(); - - b.ToTable("identity_users", null, t => - { - t.HasComment("管理后台账户实体(平台管理员、租户管理员或商户员工)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.MiniUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Avatar") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Nickname") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称。"); - - b.Property("OpenId") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("微信 OpenId。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UnionId") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("微信 UnionId,可能为空。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "OpenId") - .IsUnique(); - - b.ToTable("mini_users", null, t => - { - t.HasComment("小程序用户实体。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("权限编码(租户内唯一)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("权限名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("permissions", null, t => - { - t.HasComment("权限定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.Role", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("角色编码(租户内唯一)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("角色名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("roles", null, t => - { - t.HasComment("角色定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RolePermission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PermissionId") - .HasColumnType("bigint") - .HasComment("权限 ID。"); - - b.Property("RoleId") - .HasColumnType("bigint") - .HasComment("角色 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "RoleId", "PermissionId") - .IsUnique(); - - b.ToTable("role_permissions", null, t => - { - t.HasComment("角色-权限关系。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RoleTemplate", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("模板描述。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("模板名称。"); - - b.Property("TemplateCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("模板编码(唯一)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TemplateCode") - .IsUnique(); - - b.ToTable("role_templates", null, t => - { - t.HasComment("角色模板定义(平台级)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RoleTemplatePermission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PermissionCode") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("权限编码。"); - - b.Property("RoleTemplateId") - .HasColumnType("bigint") - .HasComment("模板 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("RoleTemplateId", "PermissionCode") - .IsUnique(); - - b.ToTable("role_template_permissions", null, t => - { - t.HasComment("角色模板-权限关系(平台级)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.UserRole", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("RoleId") - .HasColumnType("bigint") - .HasComment("角色 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "UserId", "RoleId") - .IsUnique(); - - b.ToTable("user_roles", null, t => - { - t.HasComment("用户-角色关系。"); - }); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251204070039_AddRoleTemplateTables.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251204070039_AddRoleTemplateTables.cs deleted file mode 100644 index c540868..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251204070039_AddRoleTemplateTables.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.IdentityDb -{ - /// - public partial class AddRoleTemplateTables : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "role_template_permissions", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - RoleTemplateId = table.Column(type: "bigint", nullable: false, comment: "模板 ID。"), - PermissionCode = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, comment: "权限编码。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。") - }, - constraints: table => - { - table.PrimaryKey("PK_role_template_permissions", x => x.Id); - }, - comment: "角色模板-权限关系(平台级)。"); - - migrationBuilder.CreateTable( - name: "role_templates", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - TemplateCode = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "模板编码(唯一)。"), - Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, comment: "模板名称。"), - Description = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "模板描述。"), - IsActive = table.Column(type: "boolean", nullable: false, comment: "是否启用。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。") - }, - constraints: table => - { - table.PrimaryKey("PK_role_templates", x => x.Id); - }, - comment: "角色模板定义(平台级)。"); - - migrationBuilder.CreateIndex( - name: "IX_role_template_permissions_RoleTemplateId_PermissionCode", - table: "role_template_permissions", - columns: new[] { "RoleTemplateId", "PermissionCode" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_role_templates_TemplateCode", - table: "role_templates", - column: "TemplateCode", - unique: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "role_template_permissions"); - - migrationBuilder.DropTable( - name: "role_templates"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251204070108_AddRoleTemplateModel.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251204070108_AddRoleTemplateModel.Designer.cs deleted file mode 100644 index 641de90..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251204070108_AddRoleTemplateModel.Designer.cs +++ /dev/null @@ -1,548 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.Identity.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.IdentityDb -{ - [DbContext(typeof(IdentityDbContext))] - [Migration("20251204070108_AddRoleTemplateModel")] - partial class AddRoleTemplateModel - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.IdentityUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Account") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("登录账号。"); - - b.Property("Avatar") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("展示名称。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户(平台管理员为空)。"); - - b.Property("PasswordHash") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("密码哈希。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Account") - .IsUnique(); - - b.ToTable("identity_users", null, t => - { - t.HasComment("管理后台账户实体(平台管理员、租户管理员或商户员工)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.MiniUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Avatar") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Nickname") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称。"); - - b.Property("OpenId") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("微信 OpenId。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UnionId") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("微信 UnionId,可能为空。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "OpenId") - .IsUnique(); - - b.ToTable("mini_users", null, t => - { - t.HasComment("小程序用户实体。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("权限编码(租户内唯一)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("权限名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("permissions", null, t => - { - t.HasComment("权限定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.Role", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("角色编码(租户内唯一)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("角色名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("roles", null, t => - { - t.HasComment("角色定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RolePermission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PermissionId") - .HasColumnType("bigint") - .HasComment("权限 ID。"); - - b.Property("RoleId") - .HasColumnType("bigint") - .HasComment("角色 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "RoleId", "PermissionId") - .IsUnique(); - - b.ToTable("role_permissions", null, t => - { - t.HasComment("角色-权限关系。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RoleTemplate", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("模板描述。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("模板名称。"); - - b.Property("TemplateCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("模板编码(唯一)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TemplateCode") - .IsUnique(); - - b.ToTable("role_templates", null, t => - { - t.HasComment("角色模板定义(平台级)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RoleTemplatePermission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PermissionCode") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("权限编码。"); - - b.Property("RoleTemplateId") - .HasColumnType("bigint") - .HasComment("模板 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("RoleTemplateId", "PermissionCode") - .IsUnique(); - - b.ToTable("role_template_permissions", null, t => - { - t.HasComment("角色模板-权限关系(平台级)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.UserRole", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("RoleId") - .HasColumnType("bigint") - .HasComment("角色 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "UserId", "RoleId") - .IsUnique(); - - b.ToTable("user_roles", null, t => - { - t.HasComment("用户-角色关系。"); - }); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251204070108_AddRoleTemplateModel.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251204070108_AddRoleTemplateModel.cs deleted file mode 100644 index c3d38e4..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251204070108_AddRoleTemplateModel.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.IdentityDb -{ - /// - public partial class AddRoleTemplateModel : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251205131436_AddMenuDefinitions.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251205131436_AddMenuDefinitions.Designer.cs deleted file mode 100644 index 52a63a8..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251205131436_AddMenuDefinitions.Designer.cs +++ /dev/null @@ -1,667 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.Identity.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.IdentityDb -{ - [DbContext(typeof(IdentityDbContext))] - [Migration("20251205131436_AddMenuDefinitions")] - partial class AddMenuDefinitions - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.IdentityUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Account") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("登录账号。"); - - b.Property("Avatar") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("展示名称。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户(平台管理员为空)。"); - - b.Property("PasswordHash") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("密码哈希。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Account") - .IsUnique(); - - b.ToTable("identity_users", null, t => - { - t.HasComment("管理后台账户实体(平台管理员、租户管理员或商户员工)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.MenuDefinition", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthListJson") - .HasColumnType("text") - .HasComment("按钮权限列表 JSON(存储 MenuAuthItemDto 数组)。"); - - b.Property("Component") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("组件路径(不含 .vue)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Icon") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("图标标识。"); - - b.Property("IsIframe") - .HasColumnType("boolean") - .HasComment("是否 iframe。"); - - b.Property("KeepAlive") - .HasColumnType("boolean") - .HasComment("是否缓存。"); - - b.Property("Link") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("外链或 iframe 地址。"); - - b.Property("MetaPermissions") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Meta.permissions(逗号分隔)。"); - - b.Property("MetaRoles") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Meta.roles(逗号分隔)。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("菜单名称(前端路由 name)。"); - - b.Property("ParentId") - .HasColumnType("bigint") - .HasComment("父级菜单 ID,根节点为 0。"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("路由路径。"); - - b.Property("RequiredPermissions") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("访问该菜单所需的权限集合(逗号分隔)。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ParentId", "SortOrder"); - - b.ToTable("menu_definitions", null, t => - { - t.HasComment("管理端菜单定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.MiniUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Avatar") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Nickname") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称。"); - - b.Property("OpenId") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("微信 OpenId。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UnionId") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("微信 UnionId,可能为空。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "OpenId") - .IsUnique(); - - b.ToTable("mini_users", null, t => - { - t.HasComment("小程序用户实体。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("权限编码(租户内唯一)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("权限名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("permissions", null, t => - { - t.HasComment("权限定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.Role", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("角色编码(租户内唯一)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("角色名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("roles", null, t => - { - t.HasComment("角色定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RolePermission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PermissionId") - .HasColumnType("bigint") - .HasComment("权限 ID。"); - - b.Property("RoleId") - .HasColumnType("bigint") - .HasComment("角色 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "RoleId", "PermissionId") - .IsUnique(); - - b.ToTable("role_permissions", null, t => - { - t.HasComment("角色-权限关系。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RoleTemplate", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("模板描述。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("模板名称。"); - - b.Property("TemplateCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("模板编码(唯一)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TemplateCode") - .IsUnique(); - - b.ToTable("role_templates", null, t => - { - t.HasComment("角色模板定义(平台级)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RoleTemplatePermission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PermissionCode") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("权限编码。"); - - b.Property("RoleTemplateId") - .HasColumnType("bigint") - .HasComment("模板 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("RoleTemplateId", "PermissionCode") - .IsUnique(); - - b.ToTable("role_template_permissions", null, t => - { - t.HasComment("角色模板-权限关系(平台级)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.UserRole", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("RoleId") - .HasColumnType("bigint") - .HasComment("角色 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "UserId", "RoleId") - .IsUnique(); - - b.ToTable("user_roles", null, t => - { - t.HasComment("用户-角色关系。"); - }); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251205131436_AddMenuDefinitions.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251205131436_AddMenuDefinitions.cs deleted file mode 100644 index 7713d9b..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251205131436_AddMenuDefinitions.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.IdentityDb -{ - /// - public partial class AddMenuDefinitions : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "menu_definitions", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - ParentId = table.Column(type: "bigint", nullable: false, comment: "父级菜单 ID,根节点为 0。"), - Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "菜单名称(前端路由 name)。"), - Path = table.Column(type: "character varying(256)", maxLength: 256, nullable: false, comment: "路由路径。"), - Component = table.Column(type: "character varying(256)", maxLength: 256, nullable: false, comment: "组件路径(不含 .vue)。"), - Title = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, comment: "标题。"), - Icon = table.Column(type: "character varying(64)", maxLength: 64, nullable: true, comment: "图标标识。"), - IsIframe = table.Column(type: "boolean", nullable: false, comment: "是否 iframe。"), - Link = table.Column(type: "character varying(512)", maxLength: 512, nullable: true, comment: "外链或 iframe 地址。"), - KeepAlive = table.Column(type: "boolean", nullable: false, comment: "是否缓存。"), - SortOrder = table.Column(type: "integer", nullable: false, comment: "排序。"), - RequiredPermissions = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: false, comment: "访问该菜单所需的权限集合(逗号分隔)。"), - MetaPermissions = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: false, comment: "Meta.permissions(逗号分隔)。"), - MetaRoles = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: false, comment: "Meta.roles(逗号分隔)。"), - AuthListJson = table.Column(type: "text", nullable: true, comment: "按钮权限列表 JSON(存储 MenuAuthItemDto 数组)。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_menu_definitions", x => x.Id); - }, - comment: "管理端菜单定义。"); - - migrationBuilder.CreateIndex( - name: "IX_menu_definitions_TenantId_ParentId_SortOrder", - table: "menu_definitions", - columns: new[] { "TenantId", "ParentId", "SortOrder" }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "menu_definitions"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251206021946_AddPermissionHierarchyFields.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251206021946_AddPermissionHierarchyFields.Designer.cs deleted file mode 100644 index f806b14..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251206021946_AddPermissionHierarchyFields.Designer.cs +++ /dev/null @@ -1,683 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.Identity.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.IdentityDb -{ - [DbContext(typeof(IdentityDbContext))] - [Migration("20251206021946_AddPermissionHierarchyFields")] - partial class AddPermissionHierarchyFields - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.IdentityUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Account") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("登录账号。"); - - b.Property("Avatar") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("展示名称。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户(平台管理员为空)。"); - - b.Property("PasswordHash") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("密码哈希。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Account") - .IsUnique(); - - b.ToTable("identity_users", null, t => - { - t.HasComment("管理后台账户实体(平台管理员、租户管理员或商户员工)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.MenuDefinition", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthListJson") - .HasColumnType("text") - .HasComment("按钮权限列表 JSON(存储 MenuAuthItemDto 数组)。"); - - b.Property("Component") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("组件路径(不含 .vue)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Icon") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("图标标识。"); - - b.Property("IsIframe") - .HasColumnType("boolean") - .HasComment("是否 iframe。"); - - b.Property("KeepAlive") - .HasColumnType("boolean") - .HasComment("是否缓存。"); - - b.Property("Link") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("外链或 iframe 地址。"); - - b.Property("MetaPermissions") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Meta.permissions(逗号分隔)。"); - - b.Property("MetaRoles") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Meta.roles(逗号分隔)。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("菜单名称(前端路由 name)。"); - - b.Property("ParentId") - .HasColumnType("bigint") - .HasComment("父级菜单 ID,根节点为 0。"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("路由路径。"); - - b.Property("RequiredPermissions") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("访问该菜单所需的权限集合(逗号分隔)。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ParentId", "SortOrder"); - - b.ToTable("menu_definitions", null, t => - { - t.HasComment("管理端菜单定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.MiniUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Avatar") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Nickname") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称。"); - - b.Property("OpenId") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("微信 OpenId。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UnionId") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("微信 UnionId,可能为空。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "OpenId") - .IsUnique(); - - b.ToTable("mini_users", null, t => - { - t.HasComment("小程序用户实体。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("权限编码(租户内唯一)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("权限名称。"); - - b.Property("ParentId") - .HasColumnType("bigint") - .HasComment("父级权限 ID,根节点为 0。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值,值越小越靠前。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("权限类型(group/leaf)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.HasIndex("TenantId", "ParentId", "SortOrder"); - - b.ToTable("permissions", null, t => - { - t.HasComment("权限定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.Role", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("角色编码(租户内唯一)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("角色名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("roles", null, t => - { - t.HasComment("角色定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RolePermission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PermissionId") - .HasColumnType("bigint") - .HasComment("权限 ID。"); - - b.Property("RoleId") - .HasColumnType("bigint") - .HasComment("角色 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "RoleId", "PermissionId") - .IsUnique(); - - b.ToTable("role_permissions", null, t => - { - t.HasComment("角色-权限关系。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RoleTemplate", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("模板描述。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("模板名称。"); - - b.Property("TemplateCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("模板编码(唯一)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TemplateCode") - .IsUnique(); - - b.ToTable("role_templates", null, t => - { - t.HasComment("角色模板定义(平台级)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RoleTemplatePermission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PermissionCode") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("权限编码。"); - - b.Property("RoleTemplateId") - .HasColumnType("bigint") - .HasComment("模板 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("RoleTemplateId", "PermissionCode") - .IsUnique(); - - b.ToTable("role_template_permissions", null, t => - { - t.HasComment("角色模板-权限关系(平台级)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.UserRole", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("RoleId") - .HasColumnType("bigint") - .HasComment("角色 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "UserId", "RoleId") - .IsUnique(); - - b.ToTable("user_roles", null, t => - { - t.HasComment("用户-角色关系。"); - }); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251206021946_AddPermissionHierarchyFields.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251206021946_AddPermissionHierarchyFields.cs deleted file mode 100644 index 65de3d4..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251206021946_AddPermissionHierarchyFields.cs +++ /dev/null @@ -1,67 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.IdentityDb -{ - /// - public partial class AddPermissionHierarchyFields : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "ParentId", - table: "permissions", - type: "bigint", - nullable: false, - defaultValue: 0L, - comment: "父级权限 ID,根节点为 0。"); - - migrationBuilder.AddColumn( - name: "SortOrder", - table: "permissions", - type: "integer", - nullable: false, - defaultValue: 0, - comment: "排序值,值越小越靠前。"); - - migrationBuilder.AddColumn( - name: "Type", - table: "permissions", - type: "character varying(16)", - maxLength: 16, - nullable: false, - defaultValue: "leaf", - comment: "权限类型(group/leaf)。"); - - migrationBuilder.CreateIndex( - name: "IX_permissions_TenantId_ParentId_SortOrder", - table: "permissions", - columns: new[] { "TenantId", "ParentId", "SortOrder" }); - - migrationBuilder.Sql( - "UPDATE \"permissions\" SET \"Type\" = 'leaf' WHERE \"Type\" IS NULL OR \"Type\" = '';"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_permissions_TenantId_ParentId_SortOrder", - table: "permissions"); - - migrationBuilder.DropColumn( - name: "ParentId", - table: "permissions"); - - migrationBuilder.DropColumn( - name: "SortOrder", - table: "permissions"); - - migrationBuilder.DropColumn( - name: "Type", - table: "permissions"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251217092230_FixIdentitySchemaMismatch.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251217092230_FixIdentitySchemaMismatch.Designer.cs deleted file mode 100644 index 6acfbd3..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251217092230_FixIdentitySchemaMismatch.Designer.cs +++ /dev/null @@ -1,681 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.Identity.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.IdentityDb -{ - [DbContext(typeof(IdentityDbContext))] - [Migration("20251217092230_FixIdentitySchemaMismatch")] - partial class FixIdentitySchemaMismatch - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.IdentityUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Account") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("登录账号。"); - - b.Property("Avatar") - .HasColumnType("text") - .HasComment("头像地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("展示名称。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户(平台管理员为空)。"); - - b.Property("PasswordHash") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("密码哈希。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Account") - .IsUnique(); - - b.ToTable("identity_users", null, t => - { - t.HasComment("管理后台账户实体(平台管理员、租户管理员或商户员工)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.MenuDefinition", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthListJson") - .HasColumnType("text") - .HasComment("按钮权限列表 JSON(存储 MenuAuthItemDto 数组)。"); - - b.Property("Component") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("组件路径(不含 .vue)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Icon") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("图标标识。"); - - b.Property("IsIframe") - .HasColumnType("boolean") - .HasComment("是否 iframe。"); - - b.Property("KeepAlive") - .HasColumnType("boolean") - .HasComment("是否缓存。"); - - b.Property("Link") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("外链或 iframe 地址。"); - - b.Property("MetaPermissions") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Meta.permissions(逗号分隔)。"); - - b.Property("MetaRoles") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Meta.roles(逗号分隔)。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("菜单名称(前端路由 name)。"); - - b.Property("ParentId") - .HasColumnType("bigint") - .HasComment("父级菜单 ID,根节点为 0。"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("路由路径。"); - - b.Property("RequiredPermissions") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("访问该菜单所需的权限集合(逗号分隔)。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ParentId", "SortOrder"); - - b.ToTable("menu_definitions", null, t => - { - t.HasComment("管理端菜单定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.MiniUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Avatar") - .HasColumnType("text") - .HasComment("头像地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Nickname") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称。"); - - b.Property("OpenId") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("微信 OpenId。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UnionId") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("微信 UnionId,可能为空。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "OpenId") - .IsUnique(); - - b.ToTable("mini_users", null, t => - { - t.HasComment("小程序用户实体。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("权限编码(租户内唯一)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("权限名称。"); - - b.Property("ParentId") - .HasColumnType("bigint") - .HasComment("父级权限 ID,根节点为 0。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值,值越小越靠前。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("权限类型(group/leaf)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.HasIndex("TenantId", "ParentId", "SortOrder"); - - b.ToTable("permissions", null, t => - { - t.HasComment("权限定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.Role", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("角色编码(租户内唯一)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("角色名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("roles", null, t => - { - t.HasComment("角色定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RolePermission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PermissionId") - .HasColumnType("bigint") - .HasComment("权限 ID。"); - - b.Property("RoleId") - .HasColumnType("bigint") - .HasComment("角色 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "RoleId", "PermissionId") - .IsUnique(); - - b.ToTable("role_permissions", null, t => - { - t.HasComment("角色-权限关系。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RoleTemplate", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("模板描述。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("模板名称。"); - - b.Property("TemplateCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("模板编码(唯一)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TemplateCode") - .IsUnique(); - - b.ToTable("role_templates", null, t => - { - t.HasComment("角色模板定义(平台级)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RoleTemplatePermission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PermissionCode") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("权限编码。"); - - b.Property("RoleTemplateId") - .HasColumnType("bigint") - .HasComment("模板 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("RoleTemplateId", "PermissionCode") - .IsUnique(); - - b.ToTable("role_template_permissions", null, t => - { - t.HasComment("角色模板-权限关系(平台级)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.UserRole", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("RoleId") - .HasColumnType("bigint") - .HasComment("角色 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "UserId", "RoleId") - .IsUnique(); - - b.ToTable("user_roles", null, t => - { - t.HasComment("用户-角色关系。"); - }); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251217092230_FixIdentitySchemaMismatch.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251217092230_FixIdentitySchemaMismatch.cs deleted file mode 100644 index 9bd30e4..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251217092230_FixIdentitySchemaMismatch.cs +++ /dev/null @@ -1,66 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.IdentityDb -{ - /// - public partial class FixIdentitySchemaMismatch : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "Avatar", - table: "mini_users", - type: "text", - nullable: true, - comment: "头像地址。", - oldClrType: typeof(string), - oldType: "character varying(256)", - oldMaxLength: 256, - oldNullable: true, - oldComment: "头像地址。"); - - migrationBuilder.AlterColumn( - name: "Avatar", - table: "identity_users", - type: "text", - nullable: true, - comment: "头像地址。", - oldClrType: typeof(string), - oldType: "character varying(256)", - oldMaxLength: 256, - oldNullable: true, - oldComment: "头像地址。"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "Avatar", - table: "mini_users", - type: "character varying(256)", - maxLength: 256, - nullable: true, - comment: "头像地址。", - oldClrType: typeof(string), - oldType: "text", - oldNullable: true, - oldComment: "头像地址。"); - - migrationBuilder.AlterColumn( - name: "Avatar", - table: "identity_users", - type: "character varying(256)", - maxLength: 256, - nullable: true, - comment: "头像地址。", - oldClrType: typeof(string), - oldType: "text", - oldNullable: true, - oldComment: "头像地址。"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251226174411_AddIdentityUserManagementFields.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251226174411_AddIdentityUserManagementFields.Designer.cs deleted file mode 100644 index f4bfb9c..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251226174411_AddIdentityUserManagementFields.Designer.cs +++ /dev/null @@ -1,726 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.Identity.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.IdentityDb -{ - [DbContext(typeof(IdentityDbContext))] - [Migration("20251226174411_AddIdentityUserManagementFields")] - partial class AddIdentityUserManagementFields - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.IdentityUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Account") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("登录账号。"); - - b.Property("Avatar") - .HasColumnType("text") - .HasComment("头像地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("展示名称。"); - - b.Property("Email") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("邮箱(租户内唯一)。"); - - b.Property("FailedLoginCount") - .HasColumnType("integer") - .HasComment("登录失败次数。"); - - b.Property("LastLoginAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近登录时间(UTC)。"); - - b.Property("LockedUntil") - .HasColumnType("timestamp with time zone") - .HasComment("锁定截止时间(UTC)。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户(平台管理员为空)。"); - - b.Property("MustChangePassword") - .HasColumnType("boolean") - .HasComment("是否强制修改密码。"); - - b.Property("PasswordHash") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("密码哈希。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号(租户内唯一)。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("账号状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Account") - .IsUnique(); - - b.HasIndex("TenantId", "Email") - .IsUnique() - .HasFilter("\"Email\" IS NOT NULL"); - - b.HasIndex("TenantId", "Phone") - .IsUnique() - .HasFilter("\"Phone\" IS NOT NULL"); - - b.ToTable("identity_users", null, t => - { - t.HasComment("管理后台账户实体(平台管理员、租户管理员或商户员工)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.MenuDefinition", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthListJson") - .HasColumnType("text") - .HasComment("按钮权限列表 JSON(存储 MenuAuthItemDto 数组)。"); - - b.Property("Component") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("组件路径(不含 .vue)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Icon") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("图标标识。"); - - b.Property("IsIframe") - .HasColumnType("boolean") - .HasComment("是否 iframe。"); - - b.Property("KeepAlive") - .HasColumnType("boolean") - .HasComment("是否缓存。"); - - b.Property("Link") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("外链或 iframe 地址。"); - - b.Property("MetaPermissions") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Meta.permissions(逗号分隔)。"); - - b.Property("MetaRoles") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Meta.roles(逗号分隔)。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("菜单名称(前端路由 name)。"); - - b.Property("ParentId") - .HasColumnType("bigint") - .HasComment("父级菜单 ID,根节点为 0。"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("路由路径。"); - - b.Property("RequiredPermissions") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("访问该菜单所需的权限集合(逗号分隔)。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ParentId", "SortOrder"); - - b.ToTable("menu_definitions", null, t => - { - t.HasComment("管理端菜单定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.MiniUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Avatar") - .HasColumnType("text") - .HasComment("头像地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Nickname") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称。"); - - b.Property("OpenId") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("微信 OpenId。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UnionId") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("微信 UnionId,可能为空。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "OpenId") - .IsUnique(); - - b.ToTable("mini_users", null, t => - { - t.HasComment("小程序用户实体。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("权限编码(租户内唯一)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("权限名称。"); - - b.Property("ParentId") - .HasColumnType("bigint") - .HasComment("父级权限 ID,根节点为 0。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值,值越小越靠前。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("权限类型(group/leaf)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.HasIndex("TenantId", "ParentId", "SortOrder"); - - b.ToTable("permissions", null, t => - { - t.HasComment("权限定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.Role", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("角色编码(租户内唯一)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("角色名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("roles", null, t => - { - t.HasComment("角色定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RolePermission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PermissionId") - .HasColumnType("bigint") - .HasComment("权限 ID。"); - - b.Property("RoleId") - .HasColumnType("bigint") - .HasComment("角色 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "RoleId", "PermissionId") - .IsUnique(); - - b.ToTable("role_permissions", null, t => - { - t.HasComment("角色-权限关系。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RoleTemplate", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("模板描述。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("模板名称。"); - - b.Property("TemplateCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("模板编码(唯一)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TemplateCode") - .IsUnique(); - - b.ToTable("role_templates", null, t => - { - t.HasComment("角色模板定义(平台级)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RoleTemplatePermission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PermissionCode") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("权限编码。"); - - b.Property("RoleTemplateId") - .HasColumnType("bigint") - .HasComment("模板 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("RoleTemplateId", "PermissionCode") - .IsUnique(); - - b.ToTable("role_template_permissions", null, t => - { - t.HasComment("角色模板-权限关系(平台级)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.UserRole", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("RoleId") - .HasColumnType("bigint") - .HasComment("角色 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "UserId", "RoleId") - .IsUnique(); - - b.ToTable("user_roles", null, t => - { - t.HasComment("用户-角色关系。"); - }); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251226174411_AddIdentityUserManagementFields.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251226174411_AddIdentityUserManagementFields.cs deleted file mode 100644 index a7a6f13..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251226174411_AddIdentityUserManagementFields.cs +++ /dev/null @@ -1,178 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.IdentityDb -{ - /// - public partial class AddIdentityUserManagementFields : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "Email", - table: "identity_users", - type: "character varying(128)", - maxLength: 128, - nullable: true, - comment: "邮箱(租户内唯一)。"); - - migrationBuilder.AddColumn( - name: "FailedLoginCount", - table: "identity_users", - type: "integer", - nullable: false, - defaultValue: 0, - comment: "登录失败次数。"); - - migrationBuilder.AddColumn( - name: "LastLoginAt", - table: "identity_users", - type: "timestamp with time zone", - nullable: true, - comment: "最近登录时间(UTC)。"); - - migrationBuilder.AddColumn( - name: "LockedUntil", - table: "identity_users", - type: "timestamp with time zone", - nullable: true, - comment: "锁定截止时间(UTC)。"); - - migrationBuilder.AddColumn( - name: "MustChangePassword", - table: "identity_users", - type: "boolean", - nullable: false, - defaultValue: false, - comment: "是否强制修改密码。"); - - migrationBuilder.AddColumn( - name: "Phone", - table: "identity_users", - type: "character varying(32)", - maxLength: 32, - nullable: true, - comment: "手机号(租户内唯一)。"); - - migrationBuilder.AddColumn( - name: "RowVersion", - table: "identity_users", - type: "bytea", - rowVersion: true, - nullable: false, - defaultValue: new byte[0], - comment: "并发控制字段。"); - - migrationBuilder.AddColumn( - name: "Status", - table: "identity_users", - type: "integer", - nullable: false, - defaultValue: 1, - comment: "账号状态。"); - - // 1. 修复历史用户默认状态为启用 - migrationBuilder.Sql( - """ - UPDATE identity_users - SET "Status" = 1 - WHERE "Status" = 0; - """); - - // 2. 创建 RowVersion 触发器,确保并发字段自动更新 - migrationBuilder.Sql( - """ - CREATE OR REPLACE FUNCTION public.set_identity_user_row_version() - RETURNS trigger AS $$ - BEGIN - NEW."RowVersion" = decode(md5(random()::text || clock_timestamp()::text), 'hex'); - RETURN NEW; - END; - $$ LANGUAGE plpgsql; - """); - - migrationBuilder.Sql( - """ - DROP TRIGGER IF EXISTS trg_identity_users_row_version ON identity_users; - CREATE TRIGGER trg_identity_users_row_version - BEFORE INSERT OR UPDATE ON identity_users - FOR EACH ROW EXECUTE FUNCTION public.set_identity_user_row_version(); - """); - - // 3. 回填已有数据的 RowVersion - migrationBuilder.Sql( - """ - UPDATE identity_users - SET "RowVersion" = decode(md5(random()::text || clock_timestamp()::text), 'hex') - WHERE "RowVersion" IS NULL OR octet_length("RowVersion") = 0; - """); - - migrationBuilder.CreateIndex( - name: "IX_identity_users_TenantId_Email", - table: "identity_users", - columns: new[] { "TenantId", "Email" }, - unique: true, - filter: "\"Email\" IS NOT NULL"); - - migrationBuilder.CreateIndex( - name: "IX_identity_users_TenantId_Phone", - table: "identity_users", - columns: new[] { "TenantId", "Phone" }, - unique: true, - filter: "\"Phone\" IS NOT NULL"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.Sql( - """ - DROP TRIGGER IF EXISTS trg_identity_users_row_version ON identity_users; - DROP FUNCTION IF EXISTS public.set_identity_user_row_version(); - """); - - migrationBuilder.DropIndex( - name: "IX_identity_users_TenantId_Email", - table: "identity_users"); - - migrationBuilder.DropIndex( - name: "IX_identity_users_TenantId_Phone", - table: "identity_users"); - - migrationBuilder.DropColumn( - name: "Email", - table: "identity_users"); - - migrationBuilder.DropColumn( - name: "FailedLoginCount", - table: "identity_users"); - - migrationBuilder.DropColumn( - name: "LastLoginAt", - table: "identity_users"); - - migrationBuilder.DropColumn( - name: "LockedUntil", - table: "identity_users"); - - migrationBuilder.DropColumn( - name: "MustChangePassword", - table: "identity_users"); - - migrationBuilder.DropColumn( - name: "Phone", - table: "identity_users"); - - migrationBuilder.DropColumn( - name: "RowVersion", - table: "identity_users"); - - migrationBuilder.DropColumn( - name: "Status", - table: "identity_users"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251227004313_AddIdentityOutbox.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251227004313_AddIdentityOutbox.Designer.cs deleted file mode 100644 index 9435bd5..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251227004313_AddIdentityOutbox.Designer.cs +++ /dev/null @@ -1,847 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.Identity.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.IdentityDb -{ - [DbContext(typeof(IdentityDbContext))] - [Migration("20251227004313_AddIdentityOutbox")] - partial class AddIdentityOutbox - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxMessage", b => - { - b.Property("SequenceNumber") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SequenceNumber")); - - b.Property("Body") - .IsRequired() - .HasColumnType("text"); - - b.Property("ContentType") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)"); - - b.Property("ConversationId") - .HasColumnType("uuid"); - - b.Property("CorrelationId") - .HasColumnType("uuid"); - - b.Property("DestinationAddress") - .HasMaxLength(256) - .HasColumnType("character varying(256)"); - - b.Property("EnqueueTime") - .HasColumnType("timestamp with time zone"); - - b.Property("ExpirationTime") - .HasColumnType("timestamp with time zone"); - - b.Property("FaultAddress") - .HasMaxLength(256) - .HasColumnType("character varying(256)"); - - b.Property("Headers") - .HasColumnType("text"); - - b.Property("InboxConsumerId") - .HasColumnType("uuid"); - - b.Property("InboxMessageId") - .HasColumnType("uuid"); - - b.Property("InitiatorId") - .HasColumnType("uuid"); - - b.Property("MessageId") - .HasColumnType("uuid"); - - b.Property("MessageType") - .IsRequired() - .HasColumnType("text"); - - b.Property("OutboxId") - .HasColumnType("uuid"); - - b.Property("Properties") - .HasColumnType("text"); - - b.Property("RequestId") - .HasColumnType("uuid"); - - b.Property("ResponseAddress") - .HasMaxLength(256) - .HasColumnType("character varying(256)"); - - b.Property("SentTime") - .HasColumnType("timestamp with time zone"); - - b.Property("SourceAddress") - .HasMaxLength(256) - .HasColumnType("character varying(256)"); - - b.HasKey("SequenceNumber"); - - b.HasIndex("EnqueueTime"); - - b.HasIndex("ExpirationTime"); - - b.HasIndex("OutboxId", "SequenceNumber") - .IsUnique(); - - b.HasIndex("InboxMessageId", "InboxConsumerId", "SequenceNumber") - .IsUnique(); - - b.ToTable("OutboxMessage"); - }); - - modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxState", b => - { - b.Property("OutboxId") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("Created") - .HasColumnType("timestamp with time zone"); - - b.Property("Delivered") - .HasColumnType("timestamp with time zone"); - - b.Property("LastSequenceNumber") - .HasColumnType("bigint"); - - b.Property("LockId") - .HasColumnType("uuid"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea"); - - b.HasKey("OutboxId"); - - b.HasIndex("Created"); - - b.ToTable("OutboxState"); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.IdentityUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Account") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("登录账号。"); - - b.Property("Avatar") - .HasColumnType("text") - .HasComment("头像地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("展示名称。"); - - b.Property("Email") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("邮箱(租户内唯一)。"); - - b.Property("FailedLoginCount") - .HasColumnType("integer") - .HasComment("登录失败次数。"); - - b.Property("LastLoginAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近登录时间(UTC)。"); - - b.Property("LockedUntil") - .HasColumnType("timestamp with time zone") - .HasComment("锁定截止时间(UTC)。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户(平台管理员为空)。"); - - b.Property("MustChangePassword") - .HasColumnType("boolean") - .HasComment("是否强制修改密码。"); - - b.Property("PasswordHash") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("密码哈希。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号(租户内唯一)。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("账号状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Account") - .IsUnique(); - - b.HasIndex("TenantId", "Email") - .IsUnique() - .HasFilter("\"Email\" IS NOT NULL"); - - b.HasIndex("TenantId", "Phone") - .IsUnique() - .HasFilter("\"Phone\" IS NOT NULL"); - - b.ToTable("identity_users", null, t => - { - t.HasComment("管理后台账户实体(平台管理员、租户管理员或商户员工)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.MenuDefinition", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthListJson") - .HasColumnType("text") - .HasComment("按钮权限列表 JSON(存储 MenuAuthItemDto 数组)。"); - - b.Property("Component") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("组件路径(不含 .vue)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Icon") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("图标标识。"); - - b.Property("IsIframe") - .HasColumnType("boolean") - .HasComment("是否 iframe。"); - - b.Property("KeepAlive") - .HasColumnType("boolean") - .HasComment("是否缓存。"); - - b.Property("Link") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("外链或 iframe 地址。"); - - b.Property("MetaPermissions") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Meta.permissions(逗号分隔)。"); - - b.Property("MetaRoles") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Meta.roles(逗号分隔)。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("菜单名称(前端路由 name)。"); - - b.Property("ParentId") - .HasColumnType("bigint") - .HasComment("父级菜单 ID,根节点为 0。"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("路由路径。"); - - b.Property("RequiredPermissions") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("访问该菜单所需的权限集合(逗号分隔)。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ParentId", "SortOrder"); - - b.ToTable("menu_definitions", null, t => - { - t.HasComment("管理端菜单定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.MiniUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Avatar") - .HasColumnType("text") - .HasComment("头像地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Nickname") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称。"); - - b.Property("OpenId") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("微信 OpenId。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UnionId") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("微信 UnionId,可能为空。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "OpenId") - .IsUnique(); - - b.ToTable("mini_users", null, t => - { - t.HasComment("小程序用户实体。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("权限编码(租户内唯一)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("权限名称。"); - - b.Property("ParentId") - .HasColumnType("bigint") - .HasComment("父级权限 ID,根节点为 0。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值,值越小越靠前。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("权限类型(group/leaf)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.HasIndex("TenantId", "ParentId", "SortOrder"); - - b.ToTable("permissions", null, t => - { - t.HasComment("权限定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.Role", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("角色编码(租户内唯一)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("角色名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("roles", null, t => - { - t.HasComment("角色定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RolePermission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PermissionId") - .HasColumnType("bigint") - .HasComment("权限 ID。"); - - b.Property("RoleId") - .HasColumnType("bigint") - .HasComment("角色 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "RoleId", "PermissionId") - .IsUnique(); - - b.ToTable("role_permissions", null, t => - { - t.HasComment("角色-权限关系。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RoleTemplate", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("模板描述。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("模板名称。"); - - b.Property("TemplateCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("模板编码(唯一)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TemplateCode") - .IsUnique(); - - b.ToTable("role_templates", null, t => - { - t.HasComment("角色模板定义(平台级)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RoleTemplatePermission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PermissionCode") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("权限编码。"); - - b.Property("RoleTemplateId") - .HasColumnType("bigint") - .HasComment("模板 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("RoleTemplateId", "PermissionCode") - .IsUnique(); - - b.ToTable("role_template_permissions", null, t => - { - t.HasComment("角色模板-权限关系(平台级)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.UserRole", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("RoleId") - .HasColumnType("bigint") - .HasComment("角色 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "UserId", "RoleId") - .IsUnique(); - - b.ToTable("user_roles", null, t => - { - t.HasComment("用户-角色关系。"); - }); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251227004313_AddIdentityOutbox.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251227004313_AddIdentityOutbox.cs deleted file mode 100644 index 2e903cf..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251227004313_AddIdentityOutbox.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.IdentityDb -{ - /// - public partial class AddIdentityOutbox : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "OutboxMessage", - columns: table => new - { - SequenceNumber = table.Column(type: "bigint", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - EnqueueTime = table.Column(type: "timestamp with time zone", nullable: true), - SentTime = table.Column(type: "timestamp with time zone", nullable: false), - Headers = table.Column(type: "text", nullable: true), - Properties = table.Column(type: "text", nullable: true), - InboxMessageId = table.Column(type: "uuid", nullable: true), - InboxConsumerId = table.Column(type: "uuid", nullable: true), - OutboxId = table.Column(type: "uuid", nullable: true), - MessageId = table.Column(type: "uuid", nullable: false), - ContentType = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), - MessageType = table.Column(type: "text", nullable: false), - Body = table.Column(type: "text", nullable: false), - ConversationId = table.Column(type: "uuid", nullable: true), - CorrelationId = table.Column(type: "uuid", nullable: true), - InitiatorId = table.Column(type: "uuid", nullable: true), - RequestId = table.Column(type: "uuid", nullable: true), - SourceAddress = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), - DestinationAddress = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), - ResponseAddress = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), - FaultAddress = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), - ExpirationTime = table.Column(type: "timestamp with time zone", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_OutboxMessage", x => x.SequenceNumber); - }); - - migrationBuilder.CreateTable( - name: "OutboxState", - columns: table => new - { - OutboxId = table.Column(type: "uuid", nullable: false), - LockId = table.Column(type: "uuid", nullable: false), - RowVersion = table.Column(type: "bytea", rowVersion: true, nullable: true), - Created = table.Column(type: "timestamp with time zone", nullable: false), - Delivered = table.Column(type: "timestamp with time zone", nullable: true), - LastSequenceNumber = table.Column(type: "bigint", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_OutboxState", x => x.OutboxId); - }); - - migrationBuilder.CreateIndex( - name: "IX_OutboxMessage_EnqueueTime", - table: "OutboxMessage", - column: "EnqueueTime"); - - migrationBuilder.CreateIndex( - name: "IX_OutboxMessage_ExpirationTime", - table: "OutboxMessage", - column: "ExpirationTime"); - - migrationBuilder.CreateIndex( - name: "IX_OutboxMessage_InboxMessageId_InboxConsumerId_SequenceNumber", - table: "OutboxMessage", - columns: new[] { "InboxMessageId", "InboxConsumerId", "SequenceNumber" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_OutboxMessage_OutboxId_SequenceNumber", - table: "OutboxMessage", - columns: new[] { "OutboxId", "SequenceNumber" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_OutboxState_Created", - table: "OutboxState", - column: "Created"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "OutboxMessage"); - - migrationBuilder.DropTable( - name: "OutboxState"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/IdentityDbContextModelSnapshot.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/IdentityDbContextModelSnapshot.cs deleted file mode 100644 index 07a3cad..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/IdentityDbContextModelSnapshot.cs +++ /dev/null @@ -1,844 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.Identity.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.IdentityDb -{ - [DbContext(typeof(IdentityDbContext))] - partial class IdentityDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxMessage", b => - { - b.Property("SequenceNumber") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SequenceNumber")); - - b.Property("Body") - .IsRequired() - .HasColumnType("text"); - - b.Property("ContentType") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)"); - - b.Property("ConversationId") - .HasColumnType("uuid"); - - b.Property("CorrelationId") - .HasColumnType("uuid"); - - b.Property("DestinationAddress") - .HasMaxLength(256) - .HasColumnType("character varying(256)"); - - b.Property("EnqueueTime") - .HasColumnType("timestamp with time zone"); - - b.Property("ExpirationTime") - .HasColumnType("timestamp with time zone"); - - b.Property("FaultAddress") - .HasMaxLength(256) - .HasColumnType("character varying(256)"); - - b.Property("Headers") - .HasColumnType("text"); - - b.Property("InboxConsumerId") - .HasColumnType("uuid"); - - b.Property("InboxMessageId") - .HasColumnType("uuid"); - - b.Property("InitiatorId") - .HasColumnType("uuid"); - - b.Property("MessageId") - .HasColumnType("uuid"); - - b.Property("MessageType") - .IsRequired() - .HasColumnType("text"); - - b.Property("OutboxId") - .HasColumnType("uuid"); - - b.Property("Properties") - .HasColumnType("text"); - - b.Property("RequestId") - .HasColumnType("uuid"); - - b.Property("ResponseAddress") - .HasMaxLength(256) - .HasColumnType("character varying(256)"); - - b.Property("SentTime") - .HasColumnType("timestamp with time zone"); - - b.Property("SourceAddress") - .HasMaxLength(256) - .HasColumnType("character varying(256)"); - - b.HasKey("SequenceNumber"); - - b.HasIndex("EnqueueTime"); - - b.HasIndex("ExpirationTime"); - - b.HasIndex("OutboxId", "SequenceNumber") - .IsUnique(); - - b.HasIndex("InboxMessageId", "InboxConsumerId", "SequenceNumber") - .IsUnique(); - - b.ToTable("OutboxMessage"); - }); - - modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxState", b => - { - b.Property("OutboxId") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("Created") - .HasColumnType("timestamp with time zone"); - - b.Property("Delivered") - .HasColumnType("timestamp with time zone"); - - b.Property("LastSequenceNumber") - .HasColumnType("bigint"); - - b.Property("LockId") - .HasColumnType("uuid"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea"); - - b.HasKey("OutboxId"); - - b.HasIndex("Created"); - - b.ToTable("OutboxState"); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.IdentityUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Account") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("登录账号。"); - - b.Property("Avatar") - .HasColumnType("text") - .HasComment("头像地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("展示名称。"); - - b.Property("Email") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("邮箱(租户内唯一)。"); - - b.Property("FailedLoginCount") - .HasColumnType("integer") - .HasComment("登录失败次数。"); - - b.Property("LastLoginAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近登录时间(UTC)。"); - - b.Property("LockedUntil") - .HasColumnType("timestamp with time zone") - .HasComment("锁定截止时间(UTC)。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户(平台管理员为空)。"); - - b.Property("MustChangePassword") - .HasColumnType("boolean") - .HasComment("是否强制修改密码。"); - - b.Property("PasswordHash") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("密码哈希。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号(租户内唯一)。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("账号状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Account") - .IsUnique(); - - b.HasIndex("TenantId", "Email") - .IsUnique() - .HasFilter("\"Email\" IS NOT NULL"); - - b.HasIndex("TenantId", "Phone") - .IsUnique() - .HasFilter("\"Phone\" IS NOT NULL"); - - b.ToTable("identity_users", null, t => - { - t.HasComment("管理后台账户实体(平台管理员、租户管理员或商户员工)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.MenuDefinition", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthListJson") - .HasColumnType("text") - .HasComment("按钮权限列表 JSON(存储 MenuAuthItemDto 数组)。"); - - b.Property("Component") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("组件路径(不含 .vue)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Icon") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("图标标识。"); - - b.Property("IsIframe") - .HasColumnType("boolean") - .HasComment("是否 iframe。"); - - b.Property("KeepAlive") - .HasColumnType("boolean") - .HasComment("是否缓存。"); - - b.Property("Link") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("外链或 iframe 地址。"); - - b.Property("MetaPermissions") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Meta.permissions(逗号分隔)。"); - - b.Property("MetaRoles") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Meta.roles(逗号分隔)。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("菜单名称(前端路由 name)。"); - - b.Property("ParentId") - .HasColumnType("bigint") - .HasComment("父级菜单 ID,根节点为 0。"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("路由路径。"); - - b.Property("RequiredPermissions") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("访问该菜单所需的权限集合(逗号分隔)。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ParentId", "SortOrder"); - - b.ToTable("menu_definitions", null, t => - { - t.HasComment("管理端菜单定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.MiniUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Avatar") - .HasColumnType("text") - .HasComment("头像地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Nickname") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称。"); - - b.Property("OpenId") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("微信 OpenId。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UnionId") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("微信 UnionId,可能为空。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "OpenId") - .IsUnique(); - - b.ToTable("mini_users", null, t => - { - t.HasComment("小程序用户实体。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("权限编码(租户内唯一)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("权限名称。"); - - b.Property("ParentId") - .HasColumnType("bigint") - .HasComment("父级权限 ID,根节点为 0。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值,值越小越靠前。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("权限类型(group/leaf)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.HasIndex("TenantId", "ParentId", "SortOrder"); - - b.ToTable("permissions", null, t => - { - t.HasComment("权限定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.Role", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("角色编码(租户内唯一)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("角色名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("roles", null, t => - { - t.HasComment("角色定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RolePermission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PermissionId") - .HasColumnType("bigint") - .HasComment("权限 ID。"); - - b.Property("RoleId") - .HasColumnType("bigint") - .HasComment("角色 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "RoleId", "PermissionId") - .IsUnique(); - - b.ToTable("role_permissions", null, t => - { - t.HasComment("角色-权限关系。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RoleTemplate", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("模板描述。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("模板名称。"); - - b.Property("TemplateCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("模板编码(唯一)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TemplateCode") - .IsUnique(); - - b.ToTable("role_templates", null, t => - { - t.HasComment("角色模板定义(平台级)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RoleTemplatePermission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PermissionCode") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("权限编码。"); - - b.Property("RoleTemplateId") - .HasColumnType("bigint") - .HasComment("模板 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("RoleTemplateId", "PermissionCode") - .IsUnique(); - - b.ToTable("role_template_permissions", null, t => - { - t.HasComment("角色模板-权限关系(平台级)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.UserRole", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("RoleId") - .HasColumnType("bigint") - .HasComment("角色 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "UserId", "RoleId") - .IsUnique(); - - b.ToTable("user_roles", null, t => - { - t.HasComment("用户-角色关系。"); - }); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/LogsDb/20251226091835_InitLogsDb.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/LogsDb/20251226091835_InitLogsDb.Designer.cs deleted file mode 100644 index 3adc7b7..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/LogsDb/20251226091835_InitLogsDb.Designer.cs +++ /dev/null @@ -1,335 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.Logs.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.LogsDb -{ - [DbContext(typeof(TakeoutLogsDbContext))] - [Migration("20251226091835_InitLogsDb")] - partial class InitLogsDb - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberGrowthLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChangeValue") - .HasColumnType("integer") - .HasComment("变动数量。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentValue") - .HasColumnType("integer") - .HasComment("当前成长值。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_growth_logs", null, t => - { - t.HasComment("成长值变动日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantAuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("动作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("详情描述。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("商户标识。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId"); - - b.ToTable("merchant_audit_logs", null, t => - { - t.HasComment("商户入驻审核日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.OperationLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OperationType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作类型:BatchExtend, BatchRemind, StatusChange 等。"); - - b.Property("OperatorId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人ID。"); - - b.Property("OperatorName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("操作人名称。"); - - b.Property("Parameters") - .HasColumnType("text") - .HasComment("操作参数(JSON)。"); - - b.Property("Result") - .HasColumnType("text") - .HasComment("操作结果(JSON)。"); - - b.Property("Success") - .HasColumnType("boolean") - .HasComment("是否成功。"); - - b.Property("TargetIds") - .HasColumnType("text") - .HasComment("目标ID列表(JSON)。"); - - b.Property("TargetType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("目标类型:Subscription, Bill 等。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("CreatedAt"); - - b.HasIndex("OperationType", "CreatedAt"); - - b.ToTable("operation_logs", null, t => - { - t.HasComment("运营操作日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("操作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentStatus") - .HasColumnType("integer") - .HasComment("新状态。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("详细描述。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人名称。"); - - b.Property("PreviousStatus") - .HasColumnType("integer") - .HasComment("原状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("关联的租户标识。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("日志标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.ToTable("tenant_audit_logs", null, t => - { - t.HasComment("租户运营审核日志。"); - }); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/LogsDb/20251226091835_InitLogsDb.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/LogsDb/20251226091835_InitLogsDb.cs deleted file mode 100644 index fd7090a..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/LogsDb/20251226091835_InitLogsDb.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.LogsDb -{ - /// - public partial class InitLogsDb : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - } - } -} - diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/LogsDb/20251227004337_AddOperationLogInboxMessages.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/LogsDb/20251227004337_AddOperationLogInboxMessages.Designer.cs deleted file mode 100644 index 9e305a6..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/LogsDb/20251227004337_AddOperationLogInboxMessages.Designer.cs +++ /dev/null @@ -1,358 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.Logs.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.LogsDb -{ - [DbContext(typeof(TakeoutLogsDbContext))] - [Migration("20251227004337_AddOperationLogInboxMessages")] - partial class AddOperationLogInboxMessages - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberGrowthLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChangeValue") - .HasColumnType("integer") - .HasComment("变动数量。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentValue") - .HasColumnType("integer") - .HasComment("当前成长值。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_growth_logs", null, t => - { - t.HasComment("成长值变动日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantAuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("动作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("详情描述。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("商户标识。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId"); - - b.ToTable("merchant_audit_logs", null, t => - { - t.HasComment("商户入驻审核日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.OperationLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OperationType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作类型:BatchExtend, BatchRemind, StatusChange 等。"); - - b.Property("OperatorId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人ID。"); - - b.Property("OperatorName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("操作人名称。"); - - b.Property("Parameters") - .HasColumnType("text") - .HasComment("操作参数(JSON)。"); - - b.Property("Result") - .HasColumnType("text") - .HasComment("操作结果(JSON)。"); - - b.Property("Success") - .HasColumnType("boolean") - .HasComment("是否成功。"); - - b.Property("TargetIds") - .HasColumnType("text") - .HasComment("目标ID列表(JSON)。"); - - b.Property("TargetType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("目标类型:Subscription, Bill 等。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("CreatedAt"); - - b.HasIndex("OperationType", "CreatedAt"); - - b.ToTable("operation_logs", null, t => - { - t.HasComment("运营操作日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("操作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentStatus") - .HasColumnType("integer") - .HasComment("新状态。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("详细描述。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人名称。"); - - b.Property("PreviousStatus") - .HasColumnType("integer") - .HasComment("原状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("关联的租户标识。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("日志标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.ToTable("tenant_audit_logs", null, t => - { - t.HasComment("租户运营审核日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Infrastructure.Logs.Persistence.OperationLogInboxMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConsumedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("MessageId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("MessageId") - .IsUnique(); - - b.ToTable("operation_log_inbox_messages", (string)null); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/LogsDb/20251227004337_AddOperationLogInboxMessages.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/LogsDb/20251227004337_AddOperationLogInboxMessages.cs deleted file mode 100644 index f6e1232..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/LogsDb/20251227004337_AddOperationLogInboxMessages.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.LogsDb -{ - /// - public partial class AddOperationLogInboxMessages : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "operation_log_inbox_messages", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - MessageId = table.Column(type: "uuid", nullable: false), - ConsumedAt = table.Column(type: "timestamp with time zone", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_operation_log_inbox_messages", x => x.Id); - }); - - migrationBuilder.CreateIndex( - name: "IX_operation_log_inbox_messages_MessageId", - table: "operation_log_inbox_messages", - column: "MessageId", - unique: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "operation_log_inbox_messages"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/LogsDb/20251229071940_AddMerchantManagementLogs.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/LogsDb/20251229071940_AddMerchantManagementLogs.Designer.cs deleted file mode 100644 index 5a8c373..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/LogsDb/20251229071940_AddMerchantManagementLogs.Designer.cs +++ /dev/null @@ -1,454 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.Logs.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.LogsDb -{ - [DbContext(typeof(TakeoutLogsDbContext))] - [Migration("20251229071940_AddMerchantManagementLogs")] - partial class AddMerchantManagementLogs - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.1") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberGrowthLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChangeValue") - .HasColumnType("integer") - .HasComment("变动数量。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentValue") - .HasColumnType("integer") - .HasComment("当前成长值。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_growth_logs", null, t => - { - t.HasComment("成长值变动日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantAuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("动作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("详情描述。"); - - b.Property("IpAddress") - .HasMaxLength(50) - .HasColumnType("character varying(50)") - .HasComment("操作 IP。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("商户标识。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasComment("操作人名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("character varying(200)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("MerchantId", "CreatedAt"); - - b.HasIndex("TenantId", "CreatedAt"); - - b.HasIndex("TenantId", "MerchantId"); - - b.ToTable("merchant_audit_logs", null, t => - { - t.HasComment("商户入驻审核日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantChangeLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChangeReason") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("变更原因。"); - - b.Property("ChangeType") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)") - .HasComment("变更类型。"); - - b.Property("ChangedBy") - .HasColumnType("bigint") - .HasComment("变更人 ID。"); - - b.Property("ChangedByName") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasComment("变更人名称。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("FieldName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasComment("变更字段名。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("商户标识。"); - - b.Property("NewValue") - .HasColumnType("text") - .HasComment("变更后值。"); - - b.Property("OldValue") - .HasColumnType("text") - .HasComment("变更前值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("MerchantId", "CreatedAt"); - - b.HasIndex("TenantId", "CreatedAt"); - - b.ToTable("merchant_change_logs", null, t => - { - t.HasComment("商户变更日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.OperationLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OperationType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作类型:BatchExtend, BatchRemind, StatusChange 等。"); - - b.Property("OperatorId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人ID。"); - - b.Property("OperatorName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("操作人名称。"); - - b.Property("Parameters") - .HasColumnType("text") - .HasComment("操作参数(JSON)。"); - - b.Property("Result") - .HasColumnType("text") - .HasComment("操作结果(JSON)。"); - - b.Property("Success") - .HasColumnType("boolean") - .HasComment("是否成功。"); - - b.Property("TargetIds") - .HasColumnType("text") - .HasComment("目标ID列表(JSON)。"); - - b.Property("TargetType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("目标类型:Subscription, Bill 等。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("CreatedAt"); - - b.HasIndex("OperationType", "CreatedAt"); - - b.ToTable("operation_logs", null, t => - { - t.HasComment("运营操作日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("操作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentStatus") - .HasColumnType("integer") - .HasComment("新状态。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("详细描述。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人名称。"); - - b.Property("PreviousStatus") - .HasColumnType("integer") - .HasComment("原状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("关联的租户标识。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("日志标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.ToTable("tenant_audit_logs", null, t => - { - t.HasComment("租户运营审核日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Infrastructure.Logs.Persistence.OperationLogInboxMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConsumedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("MessageId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("MessageId") - .IsUnique(); - - b.ToTable("operation_log_inbox_messages", (string)null); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/LogsDb/20251229071940_AddMerchantManagementLogs.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/LogsDb/20251229071940_AddMerchantManagementLogs.cs deleted file mode 100644 index 3da2be4..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/LogsDb/20251229071940_AddMerchantManagementLogs.cs +++ /dev/null @@ -1,141 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.LogsDb -{ - /// - public partial class AddMerchantManagementLogs : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "Title", - table: "merchant_audit_logs", - type: "character varying(200)", - maxLength: 200, - nullable: false, - comment: "标题。", - oldClrType: typeof(string), - oldType: "character varying(128)", - oldMaxLength: 128, - oldComment: "标题。"); - - migrationBuilder.AlterColumn( - name: "OperatorName", - table: "merchant_audit_logs", - type: "character varying(100)", - maxLength: 100, - nullable: true, - comment: "操作人名称。", - oldClrType: typeof(string), - oldType: "character varying(64)", - oldMaxLength: 64, - oldNullable: true, - oldComment: "操作人名称。"); - - migrationBuilder.AddColumn( - name: "IpAddress", - table: "merchant_audit_logs", - type: "character varying(50)", - maxLength: 50, - nullable: true, - comment: "操作 IP。"); - - migrationBuilder.CreateTable( - name: "merchant_change_logs", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - MerchantId = table.Column(type: "bigint", nullable: false, comment: "商户标识。"), - FieldName = table.Column(type: "character varying(100)", maxLength: 100, nullable: false, comment: "变更字段名。"), - OldValue = table.Column(type: "text", nullable: true, comment: "变更前值。"), - NewValue = table.Column(type: "text", nullable: true, comment: "变更后值。"), - ChangeType = table.Column(type: "character varying(20)", maxLength: 20, nullable: false, comment: "变更类型。"), - ChangedBy = table.Column(type: "bigint", nullable: true, comment: "变更人 ID。"), - ChangedByName = table.Column(type: "character varying(100)", maxLength: 100, nullable: true, comment: "变更人名称。"), - ChangeReason = table.Column(type: "character varying(512)", maxLength: 512, nullable: true, comment: "变更原因。"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"), - CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"), - UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"), - DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。"), - TenantId = table.Column(type: "bigint", nullable: false, comment: "所属租户 ID。") - }, - constraints: table => - { - table.PrimaryKey("PK_merchant_change_logs", x => x.Id); - }, - comment: "商户变更日志。"); - - migrationBuilder.CreateIndex( - name: "IX_merchant_audit_logs_MerchantId_CreatedAt", - table: "merchant_audit_logs", - columns: new[] { "MerchantId", "CreatedAt" }); - - migrationBuilder.CreateIndex( - name: "IX_merchant_audit_logs_TenantId_CreatedAt", - table: "merchant_audit_logs", - columns: new[] { "TenantId", "CreatedAt" }); - - migrationBuilder.CreateIndex( - name: "IX_merchant_change_logs_MerchantId_CreatedAt", - table: "merchant_change_logs", - columns: new[] { "MerchantId", "CreatedAt" }); - - migrationBuilder.CreateIndex( - name: "IX_merchant_change_logs_TenantId_CreatedAt", - table: "merchant_change_logs", - columns: new[] { "TenantId", "CreatedAt" }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "merchant_change_logs"); - - migrationBuilder.DropIndex( - name: "IX_merchant_audit_logs_MerchantId_CreatedAt", - table: "merchant_audit_logs"); - - migrationBuilder.DropIndex( - name: "IX_merchant_audit_logs_TenantId_CreatedAt", - table: "merchant_audit_logs"); - - migrationBuilder.DropColumn( - name: "IpAddress", - table: "merchant_audit_logs"); - - migrationBuilder.AlterColumn( - name: "Title", - table: "merchant_audit_logs", - type: "character varying(128)", - maxLength: 128, - nullable: false, - comment: "标题。", - oldClrType: typeof(string), - oldType: "character varying(200)", - oldMaxLength: 200, - oldComment: "标题。"); - - migrationBuilder.AlterColumn( - name: "OperatorName", - table: "merchant_audit_logs", - type: "character varying(64)", - maxLength: 64, - nullable: true, - comment: "操作人名称。", - oldClrType: typeof(string), - oldType: "character varying(100)", - oldMaxLength: 100, - oldNullable: true, - oldComment: "操作人名称。"); - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/LogsDb/TakeoutLogsDbContextModelSnapshot.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/LogsDb/TakeoutLogsDbContextModelSnapshot.cs deleted file mode 100644 index ad67000..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/LogsDb/TakeoutLogsDbContextModelSnapshot.cs +++ /dev/null @@ -1,451 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.Logs.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations.LogsDb -{ - [DbContext(typeof(TakeoutLogsDbContext))] - partial class TakeoutLogsDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.1") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberGrowthLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChangeValue") - .HasColumnType("integer") - .HasComment("变动数量。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentValue") - .HasColumnType("integer") - .HasComment("当前成长值。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_growth_logs", null, t => - { - t.HasComment("成长值变动日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantAuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("动作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("详情描述。"); - - b.Property("IpAddress") - .HasMaxLength(50) - .HasColumnType("character varying(50)") - .HasComment("操作 IP。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("商户标识。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasComment("操作人名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("character varying(200)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("MerchantId", "CreatedAt"); - - b.HasIndex("TenantId", "CreatedAt"); - - b.HasIndex("TenantId", "MerchantId"); - - b.ToTable("merchant_audit_logs", null, t => - { - t.HasComment("商户入驻审核日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantChangeLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChangeReason") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("变更原因。"); - - b.Property("ChangeType") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)") - .HasComment("变更类型。"); - - b.Property("ChangedBy") - .HasColumnType("bigint") - .HasComment("变更人 ID。"); - - b.Property("ChangedByName") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasComment("变更人名称。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("FieldName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasComment("变更字段名。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("商户标识。"); - - b.Property("NewValue") - .HasColumnType("text") - .HasComment("变更后值。"); - - b.Property("OldValue") - .HasColumnType("text") - .HasComment("变更前值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("MerchantId", "CreatedAt"); - - b.HasIndex("TenantId", "CreatedAt"); - - b.ToTable("merchant_change_logs", null, t => - { - t.HasComment("商户变更日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.OperationLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OperationType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作类型:BatchExtend, BatchRemind, StatusChange 等。"); - - b.Property("OperatorId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人ID。"); - - b.Property("OperatorName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("操作人名称。"); - - b.Property("Parameters") - .HasColumnType("text") - .HasComment("操作参数(JSON)。"); - - b.Property("Result") - .HasColumnType("text") - .HasComment("操作结果(JSON)。"); - - b.Property("Success") - .HasColumnType("boolean") - .HasComment("是否成功。"); - - b.Property("TargetIds") - .HasColumnType("text") - .HasComment("目标ID列表(JSON)。"); - - b.Property("TargetType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("目标类型:Subscription, Bill 等。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("CreatedAt"); - - b.HasIndex("OperationType", "CreatedAt"); - - b.ToTable("operation_logs", null, t => - { - t.HasComment("运营操作日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("操作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentStatus") - .HasColumnType("integer") - .HasComment("新状态。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("详细描述。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("操作人名称。"); - - b.Property("PreviousStatus") - .HasColumnType("integer") - .HasComment("原状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("关联的租户标识。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("日志标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.ToTable("tenant_audit_logs", null, t => - { - t.HasComment("租户运营审核日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Infrastructure.Logs.Persistence.OperationLogInboxMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConsumedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("MessageId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("MessageId") - .IsUnique(); - - b.ToTable("operation_log_inbox_messages", (string)null); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/TakeoutAppDbContextModelSnapshot.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/TakeoutAppDbContextModelSnapshot.cs deleted file mode 100644 index 9798c54..0000000 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/TakeoutAppDbContextModelSnapshot.cs +++ /dev/null @@ -1,7421 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using TakeoutSaaS.Infrastructure.App.Persistence; - -#nullable disable - -namespace TakeoutSaaS.Infrastructure.Migrations -{ - [DbContext(typeof(TakeoutAppDbContext))] - partial class TakeoutAppDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.1") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricAlertRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionJson") - .IsRequired() - .HasColumnType("text") - .HasComment("触发条件 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Enabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("关联指标。"); - - b.Property("NotificationChannels") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("通知渠道。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("告警级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "Severity"); - - b.ToTable("metric_alert_rules", null, t => - { - t.HasComment("指标告警规则。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricDefinition", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("指标编码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultAggregation") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("默认聚合方式。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("说明。"); - - b.Property("DimensionsJson") - .HasColumnType("text") - .HasComment("维度描述 JSON。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("指标名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("metric_definitions", null, t => - { - t.HasComment("指标定义,描述可观测的数据点。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Analytics.Entities.MetricSnapshot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DimensionKey") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("维度键(JSON)。"); - - b.Property("MetricDefinitionId") - .HasColumnType("bigint") - .HasComment("指标定义 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Value") - .HasPrecision(18, 4) - .HasColumnType("numeric(18,4)") - .HasComment("数值。"); - - b.Property("WindowEnd") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口结束。"); - - b.Property("WindowStart") - .HasColumnType("timestamp with time zone") - .HasComment("统计时间窗口开始。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MetricDefinitionId", "DimensionKey", "WindowStart", "WindowEnd") - .IsUnique(); - - b.ToTable("metric_snapshots", null, t => - { - t.HasComment("指标快照,用于大盘展示。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.Coupon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("券码或序列号。"); - - b.Property("CouponTemplateId") - .HasColumnType("bigint") - .HasComment("模板标识。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("发放时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID(已使用时记录)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedAt") - .HasColumnType("timestamp with time zone") - .HasComment("使用时间。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("归属用户。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.ToTable("coupons", null, t => - { - t.HasComment("用户领取的券。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.CouponTemplate", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowStack") - .HasColumnType("boolean") - .HasComment("是否允许叠加其他优惠。"); - - b.Property("ChannelsJson") - .HasColumnType("text") - .HasComment("发放渠道(JSON)。"); - - b.Property("ClaimedQuantity") - .HasColumnType("integer") - .HasComment("已领取数量。"); - - b.Property("CouponType") - .HasColumnType("integer") - .HasComment("券类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("DiscountCap") - .HasColumnType("numeric") - .HasComment("折扣上限(针对折扣券)。"); - - b.Property("MinimumSpend") - .HasColumnType("numeric") - .HasComment("最低消费门槛。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("模板名称。"); - - b.Property("ProductScopeJson") - .HasColumnType("text") - .HasComment("适用品类或商品范围(JSON)。"); - - b.Property("RelativeValidDays") - .HasColumnType("integer") - .HasComment("有效天数(相对发放时间)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreScopeJson") - .HasColumnType("text") - .HasComment("适用门店 ID 集合(JSON)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TotalQuantity") - .HasColumnType("integer") - .HasComment("总发放数量上限。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ValidFrom") - .HasColumnType("timestamp with time zone") - .HasComment("可用开始时间。"); - - b.Property("ValidTo") - .HasColumnType("timestamp with time zone") - .HasComment("可用结束时间。"); - - b.Property("Value") - .HasColumnType("numeric") - .HasComment("面值或折扣额度。"); - - b.HasKey("Id"); - - b.ToTable("coupon_templates", null, t => - { - t.HasComment("优惠券模板。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.PromotionCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AudienceDescription") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("目标人群描述。"); - - b.Property("BannerUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营销素材(如 banner)。"); - - b.Property("Budget") - .HasColumnType("numeric") - .HasComment("预算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("PromotionType") - .HasColumnType("integer") - .HasComment("活动类型。"); - - b.Property("RulesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("活动规则 JSON。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("活动状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("promotion_campaigns", null, t => - { - t.HasComment("营销活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChatSessionId") - .HasColumnType("bigint") - .HasComment("会话标识。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("消息内容。"); - - b.Property("ContentType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("消息类型(文字/图片/语音等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRead") - .HasColumnType("boolean") - .HasComment("是否已读。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("读取时间。"); - - b.Property("SenderType") - .HasColumnType("integer") - .HasComment("发送方类型。"); - - b.Property("SenderUserId") - .HasColumnType("bigint") - .HasComment("发送方用户 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ChatSessionId", "CreatedAt"); - - b.ToTable("chat_messages", null, t => - { - t.HasComment("会话消息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AgentUserId") - .HasColumnType("bigint") - .HasComment("当前客服员工 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("顾客用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndedAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("IsBotActive") - .HasColumnType("boolean") - .HasComment("是否机器人接待中。"); - - b.Property("SessionCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话编号。"); - - b.Property("StartedAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店(可空为平台)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionCode") - .IsUnique(); - - b.ToTable("chat_sessions", null, t => - { - t.HasComment("客服会话。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.SupportTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AssignedAgentId") - .HasColumnType("bigint") - .HasComment("指派的客服。"); - - b.Property("ClosedAt") - .HasColumnType("timestamp with time zone") - .HasComment("关闭时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerUserId") - .HasColumnType("bigint") - .HasComment("客户用户 ID。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .IsRequired() - .HasColumnType("text") - .HasComment("工单详情。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单(如有)。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("优先级。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("Subject") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("工单主题。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("工单编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TicketNo") - .IsUnique(); - - b.ToTable("support_tickets", null, t => - { - t.HasComment("客服工单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.TicketComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttachmentsJson") - .HasColumnType("text") - .HasComment("附件 JSON。"); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人 ID。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsInternal") - .HasColumnType("boolean") - .HasComment("是否内部备注。"); - - b.Property("SupportTicketId") - .HasColumnType("bigint") - .HasComment("工单标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SupportTicketId"); - - b.ToTable("ticket_comments", null, t => - { - t.HasComment("工单评论/流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryEvent", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryOrderId") - .HasColumnType("bigint") - .HasComment("配送单标识。"); - - b.Property("EventType") - .HasColumnType("integer") - .HasComment("事件类型。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("事件描述。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始数据 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DeliveryOrderId", "EventType"); - - b.ToTable("delivery_events", null, t => - { - t.HasComment("配送状态事件流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CourierName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("骑手姓名。"); - - b.Property("CourierPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("骑手电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveredAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("DispatchedAt") - .HasColumnType("timestamp with time zone") - .HasComment("下发时间。"); - - b.Property("FailureReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("异常原因。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("获取或设置关联订单 ID。"); - - b.Property("PickedUpAt") - .HasColumnType("timestamp with time zone") - .HasComment("取餐时间。"); - - b.Property("Provider") - .HasColumnType("integer") - .HasComment("配送服务商。"); - - b.Property("ProviderOrderId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方配送单号。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId") - .IsUnique(); - - b.ToTable("delivery_orders", null, t => - { - t.HasComment("配送单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliateOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("推广人标识。"); - - b.Property("BuyerUserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedCommission") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("预计佣金。"); - - b.Property("OrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("订单金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("SettledAt") - .HasColumnType("timestamp with time zone") - .HasComment("结算完成时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "OrderId") - .IsUnique(); - - b.ToTable("affiliate_orders", null, t => - { - t.HasComment("分销订单记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePartner", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChannelType") - .HasColumnType("integer") - .HasComment("渠道类型。"); - - b.Property("CommissionRate") - .HasColumnType("numeric") - .HasComment("分成比例(0-1)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称或渠道名称。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID(如绑定平台账号)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "DisplayName"); - - b.ToTable("affiliate_partners", null, t => - { - t.HasComment("分销/推广合作伙伴。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Distribution.Entities.AffiliatePayout", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AffiliatePartnerId") - .HasColumnType("bigint") - .HasComment("合作伙伴标识。"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("结算金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("打款时间。"); - - b.Property("Period") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("结算周期描述。"); - - b.Property("Remarks") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AffiliatePartnerId", "Period") - .IsUnique(); - - b.ToTable("affiliate_payouts", null, t => - { - t.HasComment("佣金结算记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInCampaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowMakeupCount") - .HasColumnType("integer") - .HasComment("支持补签次数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("活动描述。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("结束日期。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("活动名称。"); - - b.Property("RewardsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("连签奖励 JSON。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("开始日期。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name"); - - b.ToTable("checkin_campaigns", null, t => - { - t.HasComment("签到活动配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CheckInRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CheckInCampaignId") - .HasColumnType("bigint") - .HasComment("活动标识。"); - - b.Property("CheckInDate") - .HasColumnType("timestamp with time zone") - .HasComment("签到日期(本地)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsMakeup") - .HasColumnType("boolean") - .HasComment("是否补签。"); - - b.Property("RewardJson") - .IsRequired() - .HasColumnType("text") - .HasComment("获得奖励 JSON。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "CheckInCampaignId", "UserId", "CheckInDate") - .IsUnique(); - - b.ToTable("checkin_records", null, t => - { - t.HasComment("用户签到记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("评论人。"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("评论内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsDeleted") - .HasColumnType("boolean") - .HasComment("状态。"); - - b.Property("ParentId") - .HasColumnType("bigint") - .HasComment("父级评论 ID。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "CreatedAt"); - - b.ToTable("community_comments", null, t => - { - t.HasComment("社区评论。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityPost", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorUserId") - .HasColumnType("bigint") - .HasComment("作者用户 ID。"); - - b.Property("CommentCount") - .HasColumnType("integer") - .HasComment("评论数。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("内容。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LikeCount") - .HasColumnType("integer") - .HasComment("点赞数。"); - - b.Property("MediaJson") - .HasColumnType("text") - .HasComment("媒体资源 JSON。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AuthorUserId", "CreatedAt"); - - b.ToTable("community_posts", null, t => - { - t.HasComment("社区动态。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Engagement.Entities.CommunityReaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PostId") - .HasColumnType("bigint") - .HasComment("动态 ID。"); - - b.Property("ReactedAt") - .HasColumnType("timestamp with time zone") - .HasComment("时间戳。"); - - b.Property("ReactionType") - .HasColumnType("integer") - .HasComment("反应类型。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PostId", "UserId") - .IsUnique(); - - b.ToTable("community_reactions", null, t => - { - t.HasComment("社区互动反馈。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CurrentCount") - .HasColumnType("integer") - .HasComment("当前已参与人数。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndAt") - .HasColumnType("timestamp with time zone") - .HasComment("结束时间。"); - - b.Property("GroupOrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("拼单编号。"); - - b.Property("GroupPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("拼团价格。"); - - b.Property("LeaderUserId") - .HasColumnType("bigint") - .HasComment("团长用户 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("关联商品或套餐。"); - - b.Property("StartAt") - .HasColumnType("timestamp with time zone") - .HasComment("开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("拼团状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("SucceededAt") - .HasColumnType("timestamp with time zone") - .HasComment("成团时间。"); - - b.Property("TargetCount") - .HasColumnType("integer") - .HasComment("成团需要的人数。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderNo") - .IsUnique(); - - b.ToTable("group_orders", null, t => - { - t.HasComment("拼单活动。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.GroupBuying.Entities.GroupParticipant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GroupOrderId") - .HasColumnType("bigint") - .HasComment("拼单活动标识。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("参与时间。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("对应订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("参与状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "GroupOrderId", "UserId") - .IsUnique(); - - b.ToTable("group_participants", null, t => - { - t.HasComment("拼单参与者。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryAdjustment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdjustmentType") - .HasColumnType("integer") - .HasComment("调整类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("InventoryItemId") - .HasColumnType("bigint") - .HasComment("对应的库存记录标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("调整数量,正数增加,负数减少。"); - - b.Property("Reason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("原因说明。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "InventoryItemId", "OccurredAt"); - - b.ToTable("inventory_adjustments", null, t => - { - t.HasComment("库存调整记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryBatch", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("ProductionDate") - .HasColumnType("timestamp with time zone") - .HasComment("生产日期。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("入库数量。"); - - b.Property("RemainingQuantity") - .HasColumnType("integer") - .HasComment("剩余数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber") - .IsUnique(); - - b.ToTable("inventory_batches", null, t => - { - t.HasComment("SKU 批次信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BatchConsumeStrategy") - .HasColumnType("integer") - .HasComment("批次扣减策略。"); - - b.Property("BatchNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("批次编号,可为空表示混批。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireDate") - .HasColumnType("timestamp with time zone") - .HasComment("过期日期。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售商品。"); - - b.Property("IsSoldOut") - .HasColumnType("boolean") - .HasComment("是否标记售罄。"); - - b.Property("Location") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("储位或仓位信息。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单品限购(覆盖商品级 MaxQuantityPerOrder)。"); - - b.Property("PresaleCapacity") - .HasColumnType("integer") - .HasComment("预售名额(上限)。"); - - b.Property("PresaleEndTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售结束时间(UTC)。"); - - b.Property("PresaleLocked") - .HasColumnType("integer") - .HasComment("当前预售已锁定数量。"); - - b.Property("PresaleStartTime") - .HasColumnType("timestamp with time zone") - .HasComment("预售开始时间(UTC)。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("QuantityOnHand") - .HasColumnType("integer") - .HasComment("可用库存。"); - - b.Property("QuantityReserved") - .HasColumnType("integer") - .HasComment("已锁定库存(订单占用)。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("SafetyStock") - .HasColumnType("integer") - .HasComment("安全库存阈值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "BatchNumber"); - - b.ToTable("inventory_items", null, t => - { - t.HasComment("SKU 在门店的库存信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Inventory.Entities.InventoryLockRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("IdempotencyKey") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("幂等键。"); - - b.Property("IsPresale") - .HasColumnType("boolean") - .HasComment("是否预售锁定。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU ID。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("锁定数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("锁定状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "IdempotencyKey") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "ProductSkuId", "Status"); - - b.ToTable("inventory_lock_records", null, t => - { - t.HasComment("库存锁定记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberPointLedger", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BalanceAfterChange") - .HasColumnType("integer") - .HasComment("变动后余额。"); - - b.Property("ChangeAmount") - .HasColumnType("integer") - .HasComment("变动数量,可为负值。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(如适用)。"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasComment("会员标识。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("Reason") - .HasColumnType("integer") - .HasComment("变动原因。"); - - b.Property("SourceId") - .HasColumnType("bigint") - .HasComment("来源 ID(订单、活动等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MemberId", "OccurredAt"); - - b.ToTable("member_point_ledgers", null, t => - { - t.HasComment("积分变动流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AvatarUrl") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("头像。"); - - b.Property("BirthDate") - .HasColumnType("timestamp with time zone") - .HasComment("生日。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("GrowthValue") - .HasColumnType("integer") - .HasComment("成长值/经验值。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("注册时间。"); - - b.Property("MemberTierId") - .HasColumnType("bigint") - .HasComment("当前会员等级 ID。"); - - b.Property("Mobile") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("Nickname") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("昵称。"); - - b.Property("PointsBalance") - .HasColumnType("integer") - .HasComment("会员积分余额。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会员状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Mobile") - .IsUnique(); - - b.ToTable("member_profiles", null, t => - { - t.HasComment("会员档案。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Membership.Entities.MemberTier", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BenefitsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("等级权益(JSON)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("等级名称。"); - - b.Property("RequiredGrowth") - .HasColumnType("integer") - .HasComment("所需成长值。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("member_tiers", null, t => - { - t.HasComment("会员等级定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.Merchant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("ApprovedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核通过时间。"); - - b.Property("ApprovedBy") - .HasColumnType("bigint") - .HasComment("审核通过人。"); - - b.Property("BrandAlias") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("品牌简称或别名。"); - - b.Property("BrandName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("品牌名称(对外展示)。"); - - b.Property("BusinessLicenseImageUrl") - .HasColumnType("text") - .HasComment("营业执照扫描件地址。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照号。"); - - b.Property("Category") - .HasColumnType("text") - .HasComment("品牌所属品类,如火锅、咖啡等。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("ClaimExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("领取过期时间。"); - - b.Property("ClaimedAt") - .HasColumnType("timestamp with time zone") - .HasComment("领取时间。"); - - b.Property("ClaimedBy") - .HasColumnType("bigint") - .HasComment("当前领取人。"); - - b.Property("ClaimedByName") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasComment("当前领取人姓名。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("联系邮箱。"); - - b.Property("ContactPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在区县。"); - - b.Property("FrozenAt") - .HasColumnType("timestamp with time zone") - .HasComment("冻结时间。"); - - b.Property("FrozenReason") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("冻结原因。"); - - b.Property("IsFrozen") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false) - .HasComment("是否冻结业务。"); - - b.Property("JoinedAt") - .HasColumnType("timestamp with time zone") - .HasComment("入驻时间。"); - - b.Property("LastReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次审核时间。"); - - b.Property("LastReviewedBy") - .HasColumnType("bigint") - .HasComment("最近一次审核人。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度信息。"); - - b.Property("LegalPerson") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人或负责人姓名。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("品牌 Logo。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度信息。"); - - b.Property("OperatingMode") - .HasColumnType("integer") - .HasComment("经营模式(同一主体/不同主体)。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注或驳回原因。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制版本。"); - - b.Property("ServicePhone") - .HasColumnType("text") - .HasComment("客服电话。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("入驻状态。"); - - b.Property("SupportEmail") - .HasColumnType("text") - .HasComment("客服邮箱。"); - - b.Property("TaxNumber") - .HasColumnType("text") - .HasComment("税号/统一社会信用代码。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("ClaimedBy"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "Status"); - - b.ToTable("merchants", null, t => - { - t.HasComment("商户主体信息,承载入驻和资质审核结果。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DisplayOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("显示顺序,越小越靠前。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否可用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("类目名称。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Name") - .IsUnique(); - - b.ToTable("merchant_categories", null, t => - { - t.HasComment("商户可选类目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantContract", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ContractNumber") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("合同编号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同结束时间。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("合同文件存储地址。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("SignedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签署时间。"); - - b.Property("StartDate") - .HasColumnType("timestamp with time zone") - .HasComment("合同开始时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("合同状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TerminatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("终止时间。"); - - b.Property("TerminationReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("终止原因。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "ContractNumber") - .IsUnique(); - - b.ToTable("merchant_contracts", null, t => - { - t.HasComment("商户合同记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantDocument", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DocumentNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("证照编号。"); - - b.Property("DocumentType") - .HasColumnType("integer") - .HasComment("证照类型。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("到期日期。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("证照文件链接。"); - - b.Property("IssuedAt") - .HasColumnType("timestamp with time zone") - .HasComment("签发日期。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Remarks") - .HasColumnType("text") - .HasComment("审核备注或驳回原因。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("审核状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "DocumentType"); - - b.ToTable("merchant_documents", null, t => - { - t.HasComment("商户提交的资质或证照材料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.MerchantStaff", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Email") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("邮箱地址。"); - - b.Property("IdentityUserId") - .HasColumnType("bigint") - .HasComment("登录账号 ID(指向统一身份体系)。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("员工姓名。"); - - b.Property("PermissionsJson") - .HasColumnType("text") - .HasComment("自定义权限(JSON)。"); - - b.Property("Phone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("手机号。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("员工角色类型。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("员工状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("可选的关联门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "MerchantId", "Phone"); - - b.ToTable("merchant_staff", null, t => - { - t.HasComment("商户员工账号,支持门店维度分配。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.MapLocation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Landmark") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("打车/导航落点描述。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("经度。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("名称。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店 ID,可空表示独立 POI。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("map_locations", null, t => - { - t.HasComment("地图 POI 信息,用于门店定位和推荐。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Navigation.Entities.NavigationRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("来源通道(小程序、H5 等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("请求时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店 ID。"); - - b.Property("TargetApp") - .HasColumnType("integer") - .HasComment("跳转的地图应用。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户 ID。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId", "RequestedAt"); - - b.ToTable("navigation_requests", null, t => - { - t.HasComment("用户发起的导航请求日志。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("扩展 JSON(规格、加料选项等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品或 SKU 标识。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称快照。"); - - b.Property("ProductSkuId") - .HasColumnType("bigint") - .HasComment("SKU 标识。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("自定义备注(口味要求)。"); - - b.Property("ShoppingCartId") - .HasColumnType("bigint") - .HasComment("所属购物车标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价快照。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ShoppingCartId"); - - b.ToTable("cart_items", null, t => - { - t.HasComment("购物车条目。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CartItemAddon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CartItemId") - .HasColumnType("bigint") - .HasComment("所属购物车条目。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("OptionId") - .HasColumnType("bigint") - .HasComment("选项 ID(可对应 ProductAddonOption)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("cart_item_addons", null, t => - { - t.HasComment("购物车条目的加料/附加项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.CheckoutSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(UTC)。"); - - b.Property("SessionToken") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("会话 Token。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("会话状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.Property("ValidationResultJson") - .IsRequired() - .HasColumnType("text") - .HasComment("校验结果明细 JSON。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SessionToken") - .IsUnique(); - - b.ToTable("checkout_sessions", null, t => - { - t.HasComment("结账会话,记录校验上下文。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Ordering.Entities.ShoppingCart", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryPreference") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("履约方式(堂食/自提/配送)缓存。"); - - b.Property("LastModifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次修改时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("购物车状态,包含正常/锁定。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableContext") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌码或场景标识(扫码点餐)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("用户标识。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "UserId", "StoreId") - .IsUnique(); - - b.ToTable("shopping_carts", null, t => - { - t.HasComment("用户购物车,按租户/门店隔离。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.Order", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("取消原因。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("下单渠道。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("顾客姓名。"); - - b.Property("CustomerPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("顾客手机号。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryType") - .HasColumnType("integer") - .HasComment("履约类型。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("优惠金额。"); - - b.Property("FinishedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("ItemsAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("商品总额。"); - - b.Property("OrderNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("订单号。"); - - b.Property("PaidAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付时间。"); - - b.Property("PayableAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额。"); - - b.Property("PaymentStatus") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("QueueNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队号(如有)。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationId") - .HasColumnType("bigint") - .HasComment("预约 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TableNo") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("就餐桌号。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId", "Status"); - - b.ToTable("orders", null, t => - { - t.HasComment("交易订单。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .HasColumnType("text") - .HasComment("自定义属性 JSON。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("折扣金额。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单 ID。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品 ID。"); - - b.Property("ProductName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("Quantity") - .HasColumnType("integer") - .HasComment("数量。"); - - b.Property("SkuName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("SKU/规格描述。"); - - b.Property("SubTotal") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("小计。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("单位。"); - - b.Property("UnitPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("单价。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("OrderId"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("order_items", null, t => - { - t.HasComment("订单明细。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderStatusHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注信息。"); - - b.Property("OccurredAt") - .HasColumnType("timestamp with time zone") - .HasComment("发生时间。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人标识(可为空表示系统)。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("订单标识。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("变更后的状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId", "OccurredAt"); - - b.ToTable("order_status_histories", null, t => - { - t.HasComment("订单状态流转记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.RefundRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("申请金额。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("ProcessedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核完成时间。"); - - b.Property("Reason") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("申请原因。"); - - b.Property("RefundNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("退款单号。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("用户提交时间。"); - - b.Property("ReviewNotes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("审核备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "RefundNo") - .IsUnique(); - - b.ToTable("refund_requests", null, t => - { - t.HasComment("售后/退款申请。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("支付金额。"); - - b.Property("ChannelTransactionId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("第三方渠道单号。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Method") - .HasColumnType("integer") - .HasComment("支付方式。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付完成时间。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("原始回调内容。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("错误/备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TradeNo") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("平台交易号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "OrderId"); - - b.ToTable("payment_records", null, t => - { - t.HasComment("支付流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRefundRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("退款金额。"); - - b.Property("ChannelRefundId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("渠道退款流水号。"); - - b.Property("CompletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("完成时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OrderId") - .HasColumnType("bigint") - .HasComment("关联订单标识。"); - - b.Property("Payload") - .HasColumnType("text") - .HasComment("渠道返回的原始数据 JSON。"); - - b.Property("PaymentRecordId") - .HasColumnType("bigint") - .HasComment("原支付记录标识。"); - - b.Property("RequestedAt") - .HasColumnType("timestamp with time zone") - .HasComment("退款请求时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("退款状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "PaymentRecordId"); - - b.ToTable("payment_refund_records", null, t => - { - t.HasComment("支付渠道退款流水。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.Product", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CategoryId") - .HasColumnType("bigint") - .HasComment("所属分类。"); - - b.Property("CoverImage") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("主图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("商品描述。"); - - b.Property("EnableDelivery") - .HasColumnType("boolean") - .HasComment("支持配送。"); - - b.Property("EnableDineIn") - .HasColumnType("boolean") - .HasComment("支持堂食。"); - - b.Property("EnablePickup") - .HasColumnType("boolean") - .HasComment("支持自提。"); - - b.Property("GalleryImages") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("Gallery 图片逗号分隔。"); - - b.Property("IsFeatured") - .HasColumnType("boolean") - .HasComment("是否热门推荐。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("最大每单限购。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("商品名称。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("现价。"); - - b.Property("SpuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("商品编码。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("商品状态。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("库存数量(可选)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("Subtitle") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("副标题/卖点。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Unit") - .HasMaxLength(16) - .HasColumnType("character varying(16)") - .HasComment("售卖单位(份/杯等)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SpuCode") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("products", null, t => - { - t.HasComment("商品(SPU)信息。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("MaxSelect") - .HasColumnType("integer") - .HasComment("最大选择数量。"); - - b.Property("MinSelect") - .HasColumnType("integer") - .HasComment("最小选择数量。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "Name"); - - b.ToTable("product_addon_groups", null, t => - { - t.HasComment("加料/做法分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAddonOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AddonGroupId") - .HasColumnType("bigint") - .HasComment("所属加料分组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选项。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.ToTable("product_addon_options", null, t => - { - t.HasComment("加料选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("IsRequired") - .HasColumnType("boolean") - .HasComment("是否必选。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分组名称,例如“辣度”“份量”。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SelectionType") - .HasColumnType("integer") - .HasComment("选择类型(单选/多选)。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("显示排序。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("关联门店,可为空表示所有门店共享。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("product_attribute_groups", null, t => - { - t.HasComment("商品规格/属性分组。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductAttributeOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributeGroupId") - .HasColumnType("bigint") - .HasComment("所属规格组。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExtraPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("附加价格。"); - - b.Property("IsDefault") - .HasColumnType("boolean") - .HasComment("是否默认选中。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("选项名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AttributeGroupId", "Name") - .IsUnique(); - - b.ToTable("product_attribute_options", null, t => - { - t.HasComment("商品规格选项。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("分类描述。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("分类名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("所属门店。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("product_categories", null, t => - { - t.HasComment("商品分类。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductMediaAsset", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Caption") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("描述或标题。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MediaType") - .HasColumnType("integer") - .HasComment("媒体类型。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("商品标识。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Url") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("媒资链接。"); - - b.HasKey("Id"); - - b.ToTable("product_media_assets", null, t => - { - t.HasComment("商品媒资素材。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductPricingRule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ConditionsJson") - .IsRequired() - .HasColumnType("text") - .HasComment("条件描述(JSON),如会员等级、渠道等。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效结束时间。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("特殊价格。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品。"); - - b.Property("RuleType") - .HasColumnType("integer") - .HasComment("策略类型。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StartTime") - .HasColumnType("timestamp with time zone") - .HasComment("生效开始时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("WeekdaysJson") - .HasColumnType("text") - .HasComment("生效星期(JSON 数组)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ProductId", "RuleType"); - - b.ToTable("product_pricing_rules", null, t => - { - t.HasComment("商品价格策略,支持会员价/时段价等。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductSku", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AttributesJson") - .IsRequired() - .HasColumnType("text") - .HasComment("规格属性 JSON(记录选项 ID)。"); - - b.Property("Barcode") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("条形码。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("OriginalPrice") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("原价。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("售价。"); - - b.Property("ProductId") - .HasColumnType("bigint") - .HasComment("所属商品标识。"); - - b.Property("SkuCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("SKU 编码。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StockQuantity") - .HasColumnType("integer") - .HasComment("可售库存。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weight") - .HasPrecision(10, 3) - .HasColumnType("numeric(10,3)") - .HasComment("重量(千克)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "SkuCode") - .IsUnique(); - - b.ToTable("product_skus", null, t => - { - t.HasComment("商品 SKU,记录具体规格组合价格。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Queues.Entities.QueueTicket", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CalledAt") - .HasColumnType("timestamp with time zone") - .HasComment("叫号时间。"); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EstimatedWaitMinutes") - .HasColumnType("integer") - .HasComment("预计等待分钟。"); - - b.Property("ExpiredAt") - .HasColumnType("timestamp with time zone") - .HasComment("过号时间。"); - - b.Property("PartySize") - .HasColumnType("integer") - .HasComment("就餐人数。"); - - b.Property("Remark") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("获取或设置所属门店 ID。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TicketNumber") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("排队编号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId"); - - b.HasIndex("TenantId", "StoreId", "TicketNumber") - .IsUnique(); - - b.ToTable("queue_tickets", null, t => - { - t.HasComment("排队叫号。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Reservations.Entities.Reservation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone") - .HasComment("取消时间。"); - - b.Property("CheckInCode") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("核销码/到店码。"); - - b.Property("CheckedInAt") - .HasColumnType("timestamp with time zone") - .HasComment("实际签到时间。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CustomerName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("客户姓名。"); - - b.Property("CustomerPhone") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("PeopleCount") - .HasColumnType("integer") - .HasComment("用餐人数。"); - - b.Property("Remark") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("ReservationNo") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("预约号。"); - - b.Property("ReservationTime") - .HasColumnType("timestamp with time zone") - .HasComment("预约时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店。"); - - b.Property("TablePreference") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("桌型/标签。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ReservationNo") - .IsUnique(); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("reservations", null, t => - { - t.HasComment("预约/预订记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.Store", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ActivatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核通过时间。"); - - b.Property("Address") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("详细地址。"); - - b.Property("Announcement") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("门店公告。"); - - b.Property("AuditStatus") - .HasColumnType("integer") - .HasComment("审核状态。"); - - b.Property("BusinessHours") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("门店营业时段描述(备用字符串)。"); - - b.Property("BusinessLicenseImageUrl") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("门店营业执照图片地址(主体不一致模式使用)。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(50) - .HasColumnType("character varying(50)") - .HasComment("门店营业执照号(主体不一致模式使用)。"); - - b.Property("BusinessStatus") - .HasColumnType("integer") - .HasComment("经营状态。"); - - b.Property("CategoryId") - .HasColumnType("bigint") - .HasComment("行业类目 ID。"); - - b.Property("City") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在城市。"); - - b.Property("ClosureReason") - .HasColumnType("integer") - .HasComment("歇业原因。"); - - b.Property("ClosureReasonText") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("歇业原因补充说明。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("门店编码,便于扫码及外部对接。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家或地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("门店海报。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryRadiusKm") - .HasPrecision(6, 2) - .HasColumnType("numeric(6,2)") - .HasComment("默认配送半径(公里)。"); - - b.Property("Description") - .HasColumnType("text") - .HasComment("门店描述或公告。"); - - b.Property("District") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区县信息。"); - - b.Property("ForceCloseReason") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("强制关闭原因。"); - - b.Property("ForceClosedAt") - .HasColumnType("timestamp with time zone") - .HasComment("强制关闭时间。"); - - b.Property("Latitude") - .HasColumnType("double precision") - .HasComment("纬度。"); - - b.Property("LegalRepresentative") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasComment("门店法人(主体不一致模式使用)。"); - - b.Property("Longitude") - .HasColumnType("double precision") - .HasComment("高德/腾讯地图经度。"); - - b.Property("ManagerName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("门店负责人姓名。"); - - b.Property("MerchantId") - .HasColumnType("bigint") - .HasComment("所属商户标识。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("门店名称。"); - - b.Property("OwnershipType") - .HasColumnType("integer") - .HasComment("主体类型。"); - - b.Property("Phone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("联系电话。"); - - b.Property("Province") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所在省份。"); - - b.Property("RegisteredAddress") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("门店注册地址(主体不一致模式使用)。"); - - b.Property("RejectionReason") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("审核驳回原因。"); - - b.Property("SignboardImageUrl") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("门头招牌图 URL。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("门店当前运营状态。"); - - b.Property("SubmittedAt") - .HasColumnType("timestamp with time zone") - .HasComment("提交审核时间。"); - - b.Property("SupportsDelivery") - .HasColumnType("boolean") - .HasComment("是否支持配送。"); - - b.Property("SupportsDineIn") - .HasColumnType("boolean") - .HasComment("是否支持堂食。"); - - b.Property("SupportsPickup") - .HasColumnType("boolean") - .HasComment("是否支持自提。"); - - b.Property("SupportsQueueing") - .HasColumnType("boolean") - .HasComment("支持排队叫号。"); - - b.Property("SupportsReservation") - .HasColumnType("boolean") - .HasComment("支持预约。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("门店标签(逗号分隔)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("Longitude", "Latitude") - .HasFilter("\"Longitude\" IS NOT NULL AND \"Latitude\" IS NOT NULL"); - - b.HasIndex("MerchantId", "BusinessLicenseNumber") - .IsUnique() - .HasFilter("\"BusinessLicenseNumber\" IS NOT NULL AND \"Status\" <> 3"); - - b.HasIndex("TenantId", "AuditStatus"); - - b.HasIndex("TenantId", "BusinessStatus"); - - b.HasIndex("TenantId", "Code") - .IsUnique(); - - b.HasIndex("TenantId", "MerchantId"); - - b.HasIndex("TenantId", "OwnershipType"); - - b.ToTable("stores", null, t => - { - t.HasComment("门店信息,承载营业配置与能力。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreAuditRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Action") - .HasColumnType("integer") - .HasComment("操作类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("NewStatus") - .HasColumnType("integer") - .HasComment("操作后状态。"); - - b.Property("OperatorId") - .HasColumnType("bigint") - .HasComment("操作人 ID。"); - - b.Property("OperatorName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasComment("操作人名称。"); - - b.Property("PreviousStatus") - .HasColumnType("integer") - .HasComment("操作前状态。"); - - b.Property("RejectionReason") - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("驳回理由文本。"); - - b.Property("RejectionReasonId") - .HasColumnType("bigint") - .HasComment("驳回理由 ID。"); - - b.Property("Remarks") - .HasMaxLength(1000) - .HasColumnType("character varying(1000)") - .HasComment("备注。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("CreatedAt"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("store_audit_records", null, t => - { - t.HasComment("门店审核记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreBusinessHour", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CapacityLimit") - .HasColumnType("integer") - .HasComment("最大接待容量或单量限制。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DayOfWeek") - .HasColumnType("integer") - .HasComment("星期几,0 表示周日。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间(本地时间)。"); - - b.Property("HourType") - .HasColumnType("integer") - .HasComment("时段类型(正常营业、休息、预约等)。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间(本地时间)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "DayOfWeek"); - - b.ToTable("store_business_hours", null, t => - { - t.HasComment("门店营业时段配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreDeliveryZone", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DeliveryFee") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配送费。"); - - b.Property("EstimatedMinutes") - .HasColumnType("integer") - .HasComment("预计送达分钟。"); - - b.Property("MinimumOrderAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("起送价。"); - - b.Property("PolygonGeoJson") - .IsRequired() - .HasColumnType("text") - .HasComment("GeoJSON 表示的多边形范围。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("ZoneName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ZoneName"); - - b.ToTable("store_delivery_zones", null, t => - { - t.HasComment("门店配送范围配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreEmployeeShift", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间。"); - - b.Property("Notes") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("备注。"); - - b.Property("RoleType") - .HasColumnType("integer") - .HasComment("排班角色。"); - - b.Property("ShiftDate") - .HasColumnType("timestamp with time zone") - .HasComment("班次日期。"); - - b.Property("StaffId") - .HasColumnType("bigint") - .HasComment("员工标识。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "ShiftDate", "StaffId") - .IsUnique(); - - b.ToTable("store_employee_shifts", null, t => - { - t.HasComment("门店员工排班记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreFee", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BaseDeliveryFee") - .HasPrecision(10, 2) - .HasColumnType("numeric(10,2)") - .HasComment("基础配送费(元)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("FixedPackagingFee") - .HasPrecision(10, 2) - .HasColumnType("numeric(10,2)") - .HasComment("固定打包费(总计模式有效)。"); - - b.Property("FreeDeliveryThreshold") - .HasPrecision(10, 2) - .HasColumnType("numeric(10,2)") - .HasComment("免配送费门槛。"); - - b.Property("MinimumOrderAmount") - .HasPrecision(10, 2) - .HasColumnType("numeric(10,2)") - .HasComment("起送费(元)。"); - - b.Property("PackagingFeeMode") - .HasColumnType("integer") - .HasComment("打包费模式。"); - - b.Property("OrderPackagingFeeMode") - .HasColumnType("integer") - .HasComment("订单打包费规则(按订单收费时生效)。"); - - b.Property("PackagingFeeTiersJson") - .HasColumnType("text") - .HasComment("阶梯打包费配置(JSON)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId"); - - b.HasIndex("TenantId", "StoreId") - .IsUnique(); - - b.ToTable("store_fees", null, t => - { - t.HasComment("门店费用配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreHoliday", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Date") - .HasColumnType("timestamp with time zone") - .HasComment("开始日期(原 Date 字段)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone") - .HasComment("结束日期(可选,用于日期范围,如春节 1.28~2.4)。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("结束时间(IsAllDay=false 时使用)。"); - - b.Property("IsAllDay") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否全天生效。true=全天;false=仅 StartTime~EndTime 时段。"); - - b.Property("IsClosed") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否闭店(兼容旧数据,新逻辑请用 OverrideType)。"); - - b.Property("OverrideType") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("覆盖类型(闭店/临时营业/调整时间)。"); - - b.Property("Reason") - .HasMaxLength(200) - .HasColumnType("character varying(200)") - .HasComment("说明内容。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("开始时间(IsAllDay=false 时使用)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Date"); - - b.ToTable("store_holidays", null, t => - { - t.HasComment("门店临时时段配置(节假日/歇业/调整营业时间)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSetting", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowDaysAhead") - .HasColumnType("integer") - .HasComment("可预约天数(含当天)。"); - - b.Property("AllowToday") - .HasColumnType("boolean") - .HasComment("是否允许当天自提。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DefaultCutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("默认截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("MaxQuantityPerOrder") - .HasColumnType("integer") - .HasComment("单笔自提最大份数。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId") - .IsUnique(); - - b.ToTable("store_pickup_settings", null, t => - { - t.HasComment("门店自提配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StorePickupSlot", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("容量(份数)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("CutoffMinutes") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(30) - .HasComment("截单分钟(开始前多少分钟截止)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EndTime") - .HasColumnType("interval") - .HasComment("当天结束时间(UTC)。"); - - b.Property("IsEnabled") - .HasColumnType("boolean") - .HasComment("是否启用。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("档期名称。"); - - b.Property("ReservedCount") - .HasColumnType("integer") - .HasComment("已占用数量。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("StartTime") - .HasColumnType("interval") - .HasComment("当天开始时间(UTC)。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Weekdays") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("适用星期(逗号分隔 1-7)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name"); - - b.ToTable("store_pickup_slots", null, t => - { - t.HasComment("门店自提档期。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreQualification", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DocumentNumber") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasComment("证照编号。"); - - b.Property("ExpiresAt") - .HasColumnType("date") - .HasComment("到期日期。"); - - b.Property("FileUrl") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasComment("证照文件 URL。"); - - b.Property("IssuedAt") - .HasColumnType("date") - .HasComment("签发日期。"); - - b.Property("QualificationType") - .HasColumnType("integer") - .HasComment("资质类型。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(100) - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("ExpiresAt") - .HasFilter("\"ExpiresAt\" IS NOT NULL"); - - b.HasIndex("TenantId", "StoreId"); - - b.ToTable("store_qualifications", null, t => - { - t.HasComment("门店资质证照。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTable", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AreaId") - .HasColumnType("bigint") - .HasComment("所在区域 ID。"); - - b.Property("Capacity") - .HasColumnType("integer") - .HasComment("可容纳人数。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("QrCodeUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("桌码二维码地址。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前桌台状态。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TableCode") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("桌码。"); - - b.Property("Tags") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("桌台标签(堂食、快餐等)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "TableCode") - .IsUnique(); - - b.ToTable("store_tables", null, t => - { - t.HasComment("桌台信息与二维码绑定。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.StoreTableArea", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("区域描述。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("区域名称。"); - - b.Property("SortOrder") - .HasColumnType("integer") - .HasComment("排序值。"); - - b.Property("StoreId") - .HasColumnType("bigint") - .HasComment("门店标识。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "StoreId", "Name") - .IsUnique(); - - b.ToTable("store_table_areas", null, t => - { - t.HasComment("门店桌台区域配置。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.QuotaPackage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("描述。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否上架。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("配额包名称。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("价格。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型。"); - - b.Property("QuotaValue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("配额数值。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("排序。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("QuotaType", "IsActive", "SortOrder"); - - b.ToTable("quota_packages", null, t => - { - t.HasComment("配额包定义(平台提供的可购买配额包)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.Tenant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("text") - .HasComment("详细地址信息。"); - - b.Property("City") - .HasColumnType("text") - .HasComment("所在城市。"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("租户短编码,作为跨系统引用的唯一标识。"); - - b.Property("ContactEmail") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("主联系人邮箱。"); - - b.Property("ContactName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("主联系人姓名。"); - - b.Property("ContactPhone") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("主联系人电话。"); - - b.Property("Country") - .HasColumnType("text") - .HasComment("所在国家/地区。"); - - b.Property("CoverImageUrl") - .HasColumnType("text") - .HasComment("品牌海报或封面图。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("服务生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("服务到期时间(UTC)。"); - - b.Property("Industry") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("所属行业,如餐饮、零售等。"); - - b.Property("LegalEntityName") - .HasColumnType("text") - .HasComment("法人或公司主体名称。"); - - b.Property("LogoUrl") - .HasColumnType("text") - .HasComment("LOGO 图片地址。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("租户全称或品牌名称。"); - - b.Property("OperatingMode") - .HasColumnType("integer") - .HasComment("经营模式(同一主体/不同主体)。"); - - b.Property("PrimaryOwnerUserId") - .HasColumnType("bigint") - .HasComment("系统内对应的租户所有者账号 ID。"); - - b.Property("Province") - .HasColumnType("text") - .HasComment("所在省份或州。"); - - b.Property("Remarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息,用于运营记录特殊说明。"); - - b.Property("ShortName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("对外展示的简称。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("租户当前状态,涵盖审核、启用、停用等场景。"); - - b.Property("SuspendedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次暂停服务时间。"); - - b.Property("SuspensionReason") - .HasColumnType("text") - .HasComment("暂停或终止的原因说明。"); - - b.Property("Tags") - .HasColumnType("text") - .HasComment("业务标签集合(逗号分隔)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("Website") - .HasColumnType("text") - .HasComment("官网或主要宣传链接。"); - - b.HasKey("Id"); - - b.HasIndex("Code") - .IsUnique(); - - b.HasIndex("ContactPhone") - .IsUnique(); - - b.ToTable("tenants", null, t => - { - t.HasComment("平台租户信息,描述租户的生命周期与基础资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementType") - .HasColumnType("integer") - .HasComment("公告类型。"); - - b.Property("Content") - .IsRequired() - .HasColumnType("text") - .HasComment("公告正文(可为 Markdown/HTML,前端自行渲染)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("失效时间(UTC),为空表示长期有效。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否启用(已弃用,迁移期保留)。"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("展示优先级,数值越大越靠前。"); - - b.Property("PublishedAt") - .HasColumnType("timestamp with time zone") - .HasComment("实际发布时间(UTC)。"); - - b.Property("PublisherScope") - .HasColumnType("integer") - .HasComment("发布者范围。"); - - b.Property("PublisherUserId") - .HasColumnType("bigint") - .HasComment("发布者用户 ID(平台或租户后台账号)。"); - - b.Property("RevokedAt") - .HasColumnType("timestamp with time zone") - .HasComment("撤销时间(UTC)。"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasComment("并发控制字段。"); - - b.Property("ScheduledPublishAt") - .HasColumnType("timestamp with time zone") - .HasComment("预定发布时间(UTC)。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("公告状态。"); - - b.Property("TargetParameters") - .HasColumnType("text") - .HasComment("目标受众参数(JSON)。"); - - b.Property("TargetType") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("目标受众类型。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("公告标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("Status", "EffectiveFrom") - .HasFilter("\"TenantId\" = 0"); - - b.HasIndex("TenantId", "AnnouncementType", "IsActive"); - - b.HasIndex("TenantId", "EffectiveFrom", "EffectiveTo"); - - b.HasIndex("TenantId", "Status", "EffectiveFrom"); - - b.ToTable("tenant_announcements", null, t => - { - t.HasComment("租户公告。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncementRead", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AnnouncementId") - .HasColumnType("bigint") - .HasComment("公告 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("已读时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasComment("已读用户 ID(后台账号),为空表示租户级已读。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "AnnouncementId", "UserId") - .IsUnique(); - - b.ToTable("tenant_announcement_reads", null, t => - { - t.HasComment("租户公告已读记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantBillingStatement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AmountDue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("应付金额(原始金额)。"); - - b.Property("AmountPaid") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("实付金额。"); - - b.Property("BillingType") - .HasColumnType("integer") - .HasComment("账单类型(订阅账单/配额包账单/手动账单/续费账单)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Currency") - .IsRequired() - .ValueGeneratedOnAdd() - .HasMaxLength(8) - .HasColumnType("character varying(8)") - .HasDefaultValue("CNY") - .HasComment("货币类型(默认 CNY)。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("DiscountAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("折扣金额。"); - - b.Property("DueDate") - .HasColumnType("timestamp with time zone") - .HasComment("到期日。"); - - b.Property("LineItemsJson") - .HasColumnType("text") - .HasComment("账单明细 JSON,记录各项费用。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息(如:人工备注、取消原因等)。"); - - b.Property("OverdueNotifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("逾期通知时间。"); - - b.Property("PeriodEnd") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期结束时间。"); - - b.Property("PeriodStart") - .HasColumnType("timestamp with time zone") - .HasComment("账单周期开始时间。"); - - b.Property("ReminderSentAt") - .HasColumnType("timestamp with time zone") - .HasComment("提醒发送时间(续费提醒、逾期提醒等)。"); - - b.Property("StatementNo") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("账单编号,供对账查询。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("当前付款状态。"); - - b.Property("SubscriptionId") - .HasColumnType("bigint") - .HasComment("关联的订阅 ID(仅当 BillingType 为 Subscription 或 Renewal 时有值)。"); - - b.Property("TaxAmount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("税费金额。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("CreatedAt") - .HasDatabaseName("idx_billing_created_at"); - - b.HasIndex("Status", "DueDate") - .HasDatabaseName("idx_billing_status_duedate") - .HasFilter("\"Status\" IN (0, 2)"); - - b.HasIndex("TenantId", "StatementNo") - .IsUnique(); - - b.HasIndex("TenantId", "Status", "DueDate") - .HasDatabaseName("idx_billing_tenant_status_duedate"); - - b.ToTable("tenant_billing_statements", null, t => - { - t.HasComment("租户账单,用于呈现周期性收费。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantNotification", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Channel") - .HasColumnType("integer") - .HasComment("发布通道(站内、邮件、短信等)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasComment("通知正文。"); - - b.Property("MetadataJson") - .HasColumnType("text") - .HasComment("附加元数据 JSON。"); - - b.Property("ReadAt") - .HasColumnType("timestamp with time zone") - .HasComment("租户是否已阅读。"); - - b.Property("SentAt") - .HasColumnType("timestamp with time zone") - .HasComment("推送时间。"); - - b.Property("Severity") - .HasColumnType("integer") - .HasComment("通知重要级别。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("通知标题。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "Channel", "SentAt"); - - b.ToTable("tenant_notifications", null, t => - { - t.HasComment("面向租户的站内通知或消息推送。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantPackage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("套餐描述,包含适用场景、权益等。"); - - b.Property("FeaturePoliciesJson") - .HasColumnType("text") - .HasComment("权益明细 JSON,记录自定义特性开关。"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否仍启用(平台控制)。"); - - b.Property("IsAllowNewTenantPurchase") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否允许新租户购买/选择(仅影响新购)。"); - - b.Property("IsPublicVisible") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasComment("是否对外可见(展示页/套餐列表可见性)。"); - - b.Property("IsRecommended") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false) - .HasComment("是否推荐展示(运营推荐标识)。"); - - b.Property("MaxAccountCount") - .HasColumnType("integer") - .HasComment("允许创建的最大账号数。"); - - b.Property("MaxDeliveryOrders") - .HasColumnType("integer") - .HasComment("每月可调用的配送单数量上限。"); - - b.Property("MaxSmsCredits") - .HasColumnType("integer") - .HasComment("每月短信额度上限。"); - - b.Property("MaxStorageGb") - .HasColumnType("integer") - .HasComment("存储容量上限(GB)。"); - - b.Property("MaxStoreCount") - .HasColumnType("integer") - .HasComment("允许的最大门店数。"); - - b.Property("MonthlyPrice") - .HasColumnType("numeric") - .HasComment("月付价格,单位:人民币元。"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("套餐名称,展示给租户的简称。"); - - b.Property("PackageType") - .HasColumnType("integer") - .HasComment("套餐分类(试用、标准、旗舰等)。"); - - b.Property("PublishStatus") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("发布状态:0=草稿,1=已发布。"); - - b.Property("SortOrder") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasComment("展示排序,数值越小越靠前。"); - - b.PrimitiveCollection("Tags") - .IsRequired() - .HasColumnType("text[]") - .HasComment("套餐标签(用于展示与对比页)。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("YearlyPrice") - .HasColumnType("numeric") - .HasComment("年付价格,单位:人民币元。"); - - b.HasKey("Id"); - - b.HasIndex("IsActive", "SortOrder"); - - b.HasIndex("PublishStatus", "IsActive", "IsPublicVisible", "IsAllowNewTenantPurchase", "SortOrder"); - - b.ToTable("tenant_packages", null, t => - { - t.HasComment("平台提供的租户套餐定义。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantPayment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("支付金额。"); - - b.Property("BillingStatementId") - .HasColumnType("bigint") - .HasComment("关联的账单 ID。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("Method") - .HasColumnType("integer") - .HasComment("支付方式。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注信息。"); - - b.Property("PaidAt") - .HasColumnType("timestamp with time zone") - .HasComment("支付时间。"); - - b.Property("ProofUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("支付凭证 URL。"); - - b.Property("RefundReason") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("退款原因。"); - - b.Property("RefundedAt") - .HasColumnType("timestamp with time zone") - .HasComment("退款时间。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("支付状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TransactionNo") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("交易号。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("VerifiedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核时间。"); - - b.Property("VerifiedBy") - .HasColumnType("bigint") - .HasComment("审核人 ID(管理员)。"); - - b.HasKey("Id"); - - b.HasIndex("TransactionNo") - .HasDatabaseName("idx_payment_transaction_no") - .HasFilter("\"TransactionNo\" IS NOT NULL"); - - b.HasIndex("BillingStatementId", "PaidAt") - .HasDatabaseName("idx_payment_billing_paidat"); - - b.HasIndex("TenantId", "BillingStatementId"); - - b.ToTable("tenant_payments", null, t => - { - t.HasComment("租户支付记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaPackagePurchase", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ExpiredAt") - .HasColumnType("timestamp with time zone") - .HasComment("过期时间(可选)。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("Price") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("购买价格。"); - - b.Property("PurchasedAt") - .HasColumnType("timestamp with time zone") - .HasComment("购买时间。"); - - b.Property("QuotaPackageId") - .HasColumnType("bigint") - .HasComment("配额包 ID。"); - - b.Property("QuotaValue") - .HasPrecision(18, 2) - .HasColumnType("numeric(18,2)") - .HasComment("购买时的配额值。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "QuotaPackageId", "PurchasedAt"); - - b.ToTable("tenant_quota_package_purchases", null, t => - { - t.HasComment("租户配额包购买记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaUsage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LastResetAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次重置时间。"); - - b.Property("LimitValue") - .HasColumnType("numeric") - .HasComment("当前配额上限。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型,例如门店数、短信条数等。"); - - b.Property("ResetCycle") - .HasColumnType("text") - .HasComment("配额刷新周期描述(如月、年)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedValue") - .HasColumnType("numeric") - .HasComment("已消耗的数量。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "QuotaType") - .IsUnique(); - - b.ToTable("tenant_quota_usages", null, t => - { - t.HasComment("租户配额使用情况快照。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantQuotaUsageHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ChangeAmount") - .HasColumnType("numeric") - .HasComment("变更量(可选)。"); - - b.Property("ChangeReason") - .HasMaxLength(256) - .HasColumnType("character varying(256)") - .HasComment("变更原因(可选)。"); - - b.Property("ChangeType") - .HasColumnType("integer") - .HasComment("变更类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LimitValue") - .HasColumnType("numeric") - .HasComment("限额值(记录时刻的快照)。"); - - b.Property("QuotaType") - .HasColumnType("integer") - .HasComment("配额类型。"); - - b.Property("RecordedAt") - .HasColumnType("timestamp with time zone") - .HasComment("记录时间(UTC)。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.Property("UsedValue") - .HasColumnType("numeric") - .HasComment("已使用值(记录时刻的快照)。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "RecordedAt"); - - b.HasIndex("TenantId", "QuotaType", "RecordedAt"); - - b.ToTable("tenant_quota_usage_histories", null, t => - { - t.HasComment("租户配额使用历史记录(用于追踪配额上下限与使用量的时间序列变化)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantReviewClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ClaimedAt") - .HasColumnType("timestamp with time zone") - .HasComment("领取时间(UTC)。"); - - b.Property("ClaimedBy") - .HasColumnType("bigint") - .HasComment("领取人用户 ID。"); - - b.Property("ClaimedByName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("领取人名称(展示用快照)。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("ReleasedAt") - .HasColumnType("timestamp with time zone") - .HasComment("释放时间(UTC),未释放时为 null。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("被领取的租户 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("ClaimedBy"); - - b.HasIndex("TenantId") - .IsUnique() - .HasFilter("\"ReleasedAt\" IS NULL AND \"DeletedAt\" IS NULL"); - - b.ToTable("tenant_review_claims", null, t => - { - t.HasComment("租户入驻审核领取记录(防止多管理员并发审核)。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscription", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AutoRenew") - .HasColumnType("boolean") - .HasComment("是否开启自动续费。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("订阅生效时间(UTC)。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("订阅到期时间(UTC)。"); - - b.Property("NextBillingDate") - .HasColumnType("timestamp with time zone") - .HasComment("下一个计费时间,配合自动续费使用。"); - - b.Property("Notes") - .HasColumnType("text") - .HasComment("运营备注信息。"); - - b.Property("ScheduledPackageId") - .HasColumnType("bigint") - .HasComment("若已排期升降配,对应的新套餐 ID。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("订阅当前状态。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("所属租户 ID。"); - - b.Property("TenantPackageId") - .HasColumnType("bigint") - .HasComment("当前订阅关联的套餐标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantPackageId"); - - b.ToTable("tenant_subscriptions", null, t => - { - t.HasComment("租户套餐订阅记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantSubscriptionHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Amount") - .HasColumnType("numeric") - .HasComment("相关费用。"); - - b.Property("ChangeType") - .HasColumnType("integer") - .HasComment("变更类型。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("Currency") - .HasMaxLength(8) - .HasColumnType("character varying(8)") - .HasComment("币种。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效时间。"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("到期时间。"); - - b.Property("FromPackageId") - .HasColumnType("bigint") - .HasComment("原套餐 ID。"); - - b.Property("Notes") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("备注。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("租户标识。"); - - b.Property("TenantSubscriptionId") - .HasColumnType("bigint") - .HasComment("对应的订阅 ID。"); - - b.Property("ToPackageId") - .HasColumnType("bigint") - .HasComment("新套餐 ID。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "TenantSubscriptionId"); - - b.ToTable("tenant_subscription_histories", null, t => - { - t.HasComment("租户套餐订阅变更记录。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.TenantVerificationProfile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasComment("实体唯一标识。"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AdditionalDataJson") - .HasColumnType("text") - .HasComment("附加资料(JSON)。"); - - b.Property("BankAccountName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("开户名。"); - - b.Property("BankAccountNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("银行账号。"); - - b.Property("BankName") - .HasMaxLength(128) - .HasColumnType("character varying(128)") - .HasComment("银行名称。"); - - b.Property("BusinessLicenseNumber") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("营业执照编号。"); - - b.Property("BusinessLicenseUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("营业执照文件地址。"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间(UTC)。"); - - b.Property("CreatedBy") - .HasColumnType("bigint") - .HasComment("创建人用户标识,匿名或系统操作时为 null。"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasComment("软删除时间(UTC),未删除时为 null。"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasComment("删除人用户标识(软删除),未删除时为 null。"); - - b.Property("LegalPersonIdBackUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证反面。"); - - b.Property("LegalPersonIdFrontUrl") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("法人身份证正面。"); - - b.Property("LegalPersonIdNumber") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasComment("法人身份证号。"); - - b.Property("LegalPersonName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("法人姓名。"); - - b.Property("ReviewRemarks") - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasComment("审核备注。"); - - b.Property("ReviewedAt") - .HasColumnType("timestamp with time zone") - .HasComment("审核时间。"); - - b.Property("ReviewedBy") - .HasColumnType("bigint") - .HasComment("审核人 ID。"); - - b.Property("ReviewedByName") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasComment("审核人姓名。"); - - b.Property("Status") - .HasColumnType("integer") - .HasComment("实名状态。"); - - b.Property("SubmittedAt") - .HasColumnType("timestamp with time zone") - .HasComment("提交时间。"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasComment("对应的租户标识。"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("最近一次更新时间(UTC),从未更新时为 null。"); - - b.Property("UpdatedBy") - .HasColumnType("bigint") - .HasComment("最后更新人用户标识,匿名或系统操作时为 null。"); - - b.HasKey("Id"); - - b.HasIndex("TenantId") - .IsUnique(); - - b.ToTable("tenant_verification_profiles", null, t => - { - t.HasComment("租户实名认证资料。"); - }); - }); - - modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b => - { - b.HasOne("TakeoutSaaS.Domain.Orders.Entities.Order", null) - .WithMany() - .HasForeignKey("OrderId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Modules/TakeoutSaaS.Module.Dictionary/Extensions/DictionaryModuleExtensions.cs b/src/Modules/TakeoutSaaS.Module.Dictionary/Extensions/DictionaryModuleExtensions.cs deleted file mode 100644 index 97334aa..0000000 --- a/src/Modules/TakeoutSaaS.Module.Dictionary/Extensions/DictionaryModuleExtensions.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using TakeoutSaaS.Application.Dictionary.Extensions; -using TakeoutSaaS.Infrastructure.Dictionary.Extensions; - -namespace TakeoutSaaS.Module.Dictionary.Extensions; - -/// -/// 字典模块服务扩展。 -/// -public static class DictionaryModuleExtensions -{ - /// - /// 注册字典模块应用层与基础设施。 - /// - public static IServiceCollection AddDictionaryModule(this IServiceCollection services, IConfiguration configuration) - { - services.AddDictionaryApplication(); - services.AddDictionaryInfrastructure(configuration); - return services; - } -} diff --git a/src/Modules/TakeoutSaaS.Module.Messaging/Abstractions/IMessagePublisher.cs b/src/Modules/TakeoutSaaS.Module.Messaging/Abstractions/IMessagePublisher.cs deleted file mode 100644 index 456be39..0000000 --- a/src/Modules/TakeoutSaaS.Module.Messaging/Abstractions/IMessagePublisher.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace TakeoutSaaS.Module.Messaging.Abstractions; - -/// -/// 消息发布抽象。 -/// -public interface IMessagePublisher -{ - /// - /// 发布消息到指定路由键。 - /// - Task PublishAsync(string routingKey, T message, CancellationToken cancellationToken = default); -} diff --git a/src/Modules/TakeoutSaaS.Module.Messaging/Abstractions/IMessageSubscriber.cs b/src/Modules/TakeoutSaaS.Module.Messaging/Abstractions/IMessageSubscriber.cs deleted file mode 100644 index 685c523..0000000 --- a/src/Modules/TakeoutSaaS.Module.Messaging/Abstractions/IMessageSubscriber.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace TakeoutSaaS.Module.Messaging.Abstractions; - -/// -/// 消息订阅抽象。 -/// -public interface IMessageSubscriber : IAsyncDisposable -{ - /// - /// 订阅指定队列与路由键,处理后返回是否消费成功。 - /// - Task SubscribeAsync(string queue, string routingKey, Func> handler, CancellationToken cancellationToken = default); -} diff --git a/src/Modules/TakeoutSaaS.Module.Messaging/Extensions/MessagingServiceCollectionExtensions.cs b/src/Modules/TakeoutSaaS.Module.Messaging/Extensions/MessagingServiceCollectionExtensions.cs deleted file mode 100644 index f1f7081..0000000 --- a/src/Modules/TakeoutSaaS.Module.Messaging/Extensions/MessagingServiceCollectionExtensions.cs +++ /dev/null @@ -1,41 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using TakeoutSaaS.Module.Messaging.Abstractions; -using TakeoutSaaS.Module.Messaging.Options; -using TakeoutSaaS.Module.Messaging.Serialization; -using TakeoutSaaS.Module.Messaging.Services; - -namespace TakeoutSaaS.Module.Messaging.Extensions; - -/// -/// 消息队列模块注册扩展。 -/// -public static class MessagingServiceCollectionExtensions -{ - /// - /// 注册 RabbitMQ 发布/订阅能力。 - /// - public static IServiceCollection AddMessagingModule(this IServiceCollection services, IConfiguration configuration) - { - var rabbitMqSection = configuration.GetSection("RabbitMQ"); - if (!rabbitMqSection.Exists()) - { - services.AddSingleton(); - services.AddSingleton(); - return services; - } - - // 1. (空行后) 存在 RabbitMQ 配置时才启用真实 MQ 能力(启动时验证配置完整性) - services.AddOptions() - .Bind(rabbitMqSection) - .ValidateDataAnnotations() - .ValidateOnStart(); - - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - - return services; - } -} diff --git a/src/Modules/TakeoutSaaS.Module.Messaging/Options/RabbitMqOptions.cs b/src/Modules/TakeoutSaaS.Module.Messaging/Options/RabbitMqOptions.cs deleted file mode 100644 index 1b10e6e..0000000 --- a/src/Modules/TakeoutSaaS.Module.Messaging/Options/RabbitMqOptions.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Module.Messaging.Options; - -/// -/// RabbitMQ 连接与交换机配置。 -/// -public sealed class RabbitMqOptions -{ - /// - /// 主机名。 - /// - [Required] - public string Host { get; set; } = "localhost"; - - /// - /// 端口。 - /// - [Range(1, 65535)] - public int Port { get; set; } = 5672; - - /// - /// 用户名。 - /// - [Required] - public string Username { get; set; } = "guest"; - - /// - /// 密码。 - /// - [Required] - public string Password { get; set; } = "guest"; - - /// - /// 虚拟主机。 - /// - public string VirtualHost { get; set; } = "/"; - - /// - /// 默认交换机名称。 - /// - [Required] - public string Exchange { get; set; } = "takeout.events"; - - /// - /// 交换机类型,默认 topic。 - /// - public string ExchangeType { get; set; } = "topic"; - - /// - /// 消费预取数量。 - /// - [Range(1, 1000)] - public ushort PrefetchCount { get; set; } = 20; -} diff --git a/src/Modules/TakeoutSaaS.Module.Messaging/Serialization/JsonMessageSerializer.cs b/src/Modules/TakeoutSaaS.Module.Messaging/Serialization/JsonMessageSerializer.cs deleted file mode 100644 index a17186c..0000000 --- a/src/Modules/TakeoutSaaS.Module.Messaging/Serialization/JsonMessageSerializer.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Text; -using System.Text.Json; - -namespace TakeoutSaaS.Module.Messaging.Serialization; - -/// -/// 消息 JSON 序列化器。 -/// -public sealed class JsonMessageSerializer -{ - private static readonly JsonSerializerOptions DefaultOptions = new(JsonSerializerDefaults.Web); - - /// - /// 序列化消息。 - /// - public byte[] Serialize(T message) => Encoding.UTF8.GetBytes(JsonSerializer.Serialize(message, DefaultOptions)); - - /// - /// 反序列化消息。 - /// - public T? Deserialize(byte[] body) => JsonSerializer.Deserialize(body, DefaultOptions); -} diff --git a/src/Modules/TakeoutSaaS.Module.Messaging/Services/NoOpMessagePublisher.cs b/src/Modules/TakeoutSaaS.Module.Messaging/Services/NoOpMessagePublisher.cs deleted file mode 100644 index 3d139e0..0000000 --- a/src/Modules/TakeoutSaaS.Module.Messaging/Services/NoOpMessagePublisher.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Module.Messaging.Abstractions; - -namespace TakeoutSaaS.Module.Messaging.Services; - -/// -/// 空实现消息发布器:用于未配置 RabbitMQ 的开发/测试场景,避免启动依赖外部 MQ。 -/// -public sealed class NoOpMessagePublisher(ILogger logger) : IMessagePublisher -{ - /// - public Task PublishAsync(string routingKey, T message, CancellationToken cancellationToken = default) - { - logger.LogDebug( - "未配置 RabbitMQ,已跳过消息发布:RoutingKey={RoutingKey} MessageType={MessageType}", - routingKey, - typeof(T).FullName ?? typeof(T).Name); - return Task.CompletedTask; - } -} - diff --git a/src/Modules/TakeoutSaaS.Module.Messaging/Services/NoOpMessageSubscriber.cs b/src/Modules/TakeoutSaaS.Module.Messaging/Services/NoOpMessageSubscriber.cs deleted file mode 100644 index 5cfc432..0000000 --- a/src/Modules/TakeoutSaaS.Module.Messaging/Services/NoOpMessageSubscriber.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Module.Messaging.Abstractions; - -namespace TakeoutSaaS.Module.Messaging.Services; - -/// -/// 空实现消息订阅器:用于未配置 RabbitMQ 的开发/测试场景。 -/// -public sealed class NoOpMessageSubscriber(ILogger logger) : IMessageSubscriber -{ - /// - public Task SubscribeAsync(string queue, string routingKey, Func> handler, CancellationToken cancellationToken = default) - { - logger.LogWarning("未配置 RabbitMQ,消息订阅被禁用:Queue={Queue} RoutingKey={RoutingKey}", queue, routingKey); - return Task.CompletedTask; - } - - // 1. (空行后) 释放资源(NoOp 实现无实际资源) - /// - public ValueTask DisposeAsync() - { - logger.LogDebug("NoOpMessageSubscriber 已释放。"); - return ValueTask.CompletedTask; - } -} diff --git a/src/Modules/TakeoutSaaS.Module.Messaging/Services/RabbitMqConnectionFactory.cs b/src/Modules/TakeoutSaaS.Module.Messaging/Services/RabbitMqConnectionFactory.cs deleted file mode 100644 index 62935ef..0000000 --- a/src/Modules/TakeoutSaaS.Module.Messaging/Services/RabbitMqConnectionFactory.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Microsoft.Extensions.Options; -using RabbitMQ.Client; -using TakeoutSaaS.Module.Messaging.Options; - -namespace TakeoutSaaS.Module.Messaging.Services; - -/// -/// RabbitMQ 连接工厂封装。 -/// -public sealed class RabbitMqConnectionFactory(IOptionsMonitor optionsMonitor) -{ - /// - /// 创建连接。 - /// - public async Task CreateConnectionAsync(CancellationToken cancellationToken = default) - { - cancellationToken.ThrowIfCancellationRequested(); - var options = optionsMonitor.CurrentValue; - var factory = new ConnectionFactory - { - HostName = options.Host, - Port = options.Port, - UserName = options.Username, - Password = options.Password, - VirtualHost = options.VirtualHost - }; - - return await factory.CreateConnectionAsync(cancellationToken).ConfigureAwait(false); - } -} diff --git a/src/Modules/TakeoutSaaS.Module.Messaging/Services/RabbitMqMessagePublisher.cs b/src/Modules/TakeoutSaaS.Module.Messaging/Services/RabbitMqMessagePublisher.cs deleted file mode 100644 index 3354ddc..0000000 --- a/src/Modules/TakeoutSaaS.Module.Messaging/Services/RabbitMqMessagePublisher.cs +++ /dev/null @@ -1,79 +0,0 @@ -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using RabbitMQ.Client; -using TakeoutSaaS.Module.Messaging.Abstractions; -using TakeoutSaaS.Module.Messaging.Options; -using TakeoutSaaS.Module.Messaging.Serialization; - -namespace TakeoutSaaS.Module.Messaging.Services; - -/// -/// RabbitMQ 消息发布实现。 -/// -public sealed class RabbitMqMessagePublisher(RabbitMqConnectionFactory connectionFactory, IOptionsMonitor optionsMonitor, JsonMessageSerializer serializer, ILogger logger) - : IMessagePublisher, IAsyncDisposable -{ - private IConnection? _connection; - private IChannel? _channel; - private bool _disposed; - - /// - public async Task PublishAsync(string routingKey, T message, CancellationToken cancellationToken = default) - { - // 1. 确保通道可用 - await EnsureChannelAsync(cancellationToken); - var options = optionsMonitor.CurrentValue; - - var channel = _channel ?? throw new InvalidOperationException("RabbitMQ channel is not available."); - // 2. 声明交换机 - await channel.ExchangeDeclareAsync(options.Exchange, options.ExchangeType, durable: true, autoDelete: false, arguments: null, noWait: false, cancellationToken).ConfigureAwait(false); - // 3. 序列化消息并设置属性 - var body = serializer.Serialize(message); - var props = new BasicProperties(); - props.ContentType = "application/json"; - props.DeliveryMode = DeliveryModes.Persistent; - props.MessageId = Guid.NewGuid().ToString("N"); - - // 4. 发布消息 - await channel.BasicPublishAsync(options.Exchange, routingKey, mandatory: false, basicProperties: props, body: body, cancellationToken).ConfigureAwait(false); - logger.LogDebug("发布消息到交换机 {Exchange} RoutingKey {RoutingKey}", options.Exchange, routingKey); - } - - private async Task EnsureChannelAsync(CancellationToken cancellationToken) - { - if (_channel != null && _channel.IsOpen) - { - return; - } - - _connection ??= await connectionFactory.CreateConnectionAsync(cancellationToken).ConfigureAwait(false); - _channel = await _connection.CreateChannelAsync(new CreateChannelOptions(false, false, null, null), cancellationToken).ConfigureAwait(false); - } - - /// - /// 释放 RabbitMQ 资源。 - /// - public ValueTask DisposeAsync() - { - if (_disposed) - { - return ValueTask.CompletedTask; - } - - _disposed = true; - return CloseAsync(); - } - - private async ValueTask CloseAsync() - { - if (_channel != null) - { - await _channel.CloseAsync(CancellationToken.None).ConfigureAwait(false); - } - - if (_connection != null) - { - await _connection.CloseAsync(CancellationToken.None).ConfigureAwait(false); - } - } -} diff --git a/src/Modules/TakeoutSaaS.Module.Messaging/Services/RabbitMqMessageSubscriber.cs b/src/Modules/TakeoutSaaS.Module.Messaging/Services/RabbitMqMessageSubscriber.cs deleted file mode 100644 index f4a4c61..0000000 --- a/src/Modules/TakeoutSaaS.Module.Messaging/Services/RabbitMqMessageSubscriber.cs +++ /dev/null @@ -1,101 +0,0 @@ -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using RabbitMQ.Client; -using RabbitMQ.Client.Events; -using TakeoutSaaS.Module.Messaging.Abstractions; -using TakeoutSaaS.Module.Messaging.Options; -using TakeoutSaaS.Module.Messaging.Serialization; - -namespace TakeoutSaaS.Module.Messaging.Services; - -/// -/// RabbitMQ 消费者实现。 -/// -public sealed class RabbitMqMessageSubscriber(RabbitMqConnectionFactory connectionFactory, IOptionsMonitor optionsMonitor, JsonMessageSerializer serializer, ILogger logger) - : IMessageSubscriber -{ - private IConnection? _connection; - private IChannel? _channel; - private bool _disposed; - - /// - public async Task SubscribeAsync(string queue, string routingKey, Func> handler, CancellationToken cancellationToken = default) - { - // 1. 确保通道可用 - await EnsureChannelAsync(cancellationToken); - var options = optionsMonitor.CurrentValue; - - var channel = _channel ?? throw new InvalidOperationException("RabbitMQ channel is not available."); - - // 2. 声明交换机、队列及绑定 - await channel.ExchangeDeclareAsync(options.Exchange, options.ExchangeType, durable: true, autoDelete: false, arguments: null, noWait: false, cancellationToken).ConfigureAwait(false); - await channel.QueueDeclareAsync(queue, durable: true, exclusive: false, autoDelete: false, arguments: null, noWait: false, cancellationToken).ConfigureAwait(false); - await channel.QueueBindAsync(queue, options.Exchange, routingKey, arguments: null, noWait: false, cancellationToken).ConfigureAwait(false); - await channel.BasicQosAsync(0, options.PrefetchCount, global: false, cancellationToken).ConfigureAwait(false); - - // 3. 设置消费者回调 - var consumer = new AsyncEventingBasicConsumer(channel); - consumer.ReceivedAsync += async (_, ea) => - { - var message = serializer.Deserialize(ea.Body.ToArray()); - if (message == null) - { - await channel.BasicAckAsync(ea.DeliveryTag, multiple: false, cancellationToken).ConfigureAwait(false); - return; - } - - var success = false; - try - { - success = await handler(message, cancellationToken).ConfigureAwait(false); - } - catch (Exception ex) - { - logger.LogError(ex, "处理消息失败:{RoutingKey}", ea.RoutingKey); - } - - if (success) - { - await channel.BasicAckAsync(ea.DeliveryTag, multiple: false, cancellationToken).ConfigureAwait(false); - } - else - { - await channel.BasicNackAsync(ea.DeliveryTag, multiple: false, requeue: false, cancellationToken).ConfigureAwait(false); - } - }; - - // 4. 开始消费 - await channel.BasicConsumeAsync(queue, autoAck: false, consumer, cancellationToken).ConfigureAwait(false); - } - - private async Task EnsureChannelAsync(CancellationToken cancellationToken) - { - if (_channel != null && _channel.IsOpen) - { - return; - } - - _connection ??= await connectionFactory.CreateConnectionAsync(cancellationToken).ConfigureAwait(false); - _channel = await _connection.CreateChannelAsync(new CreateChannelOptions(false, false, null, null), cancellationToken).ConfigureAwait(false); - } - - /// - public async ValueTask DisposeAsync() - { - if (_disposed) - { - return; - } - - _disposed = true; - if (_channel != null) - { - await _channel.CloseAsync(CancellationToken.None).ConfigureAwait(false); - } - - if (_connection != null) - { - await _connection.CloseAsync(CancellationToken.None).ConfigureAwait(false); - } - } -} diff --git a/src/Modules/TakeoutSaaS.Module.Scheduler/Abstractions/IRecurringJobRegistrar.cs b/src/Modules/TakeoutSaaS.Module.Scheduler/Abstractions/IRecurringJobRegistrar.cs deleted file mode 100644 index 198da74..0000000 --- a/src/Modules/TakeoutSaaS.Module.Scheduler/Abstractions/IRecurringJobRegistrar.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace TakeoutSaaS.Module.Scheduler.Abstractions; - -/// -/// 周期性任务注册抽象。 -/// -public interface IRecurringJobRegistrar -{ - /// - /// 注册所有预设的周期性任务。 - /// - Task RegisterAsync(CancellationToken cancellationToken = default); -} diff --git a/src/Modules/TakeoutSaaS.Module.Scheduler/Extensions/SchedulerServiceCollectionExtensions.cs b/src/Modules/TakeoutSaaS.Module.Scheduler/Extensions/SchedulerServiceCollectionExtensions.cs deleted file mode 100644 index 337ec40..0000000 --- a/src/Modules/TakeoutSaaS.Module.Scheduler/Extensions/SchedulerServiceCollectionExtensions.cs +++ /dev/null @@ -1,85 +0,0 @@ -using Hangfire; -using Hangfire.PostgreSql; -using Microsoft.AspNetCore.Builder; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; -using TakeoutSaaS.Module.Scheduler.Abstractions; -using TakeoutSaaS.Module.Scheduler.HostedServices; -using TakeoutSaaS.Module.Scheduler.Jobs; -using TakeoutSaaS.Module.Scheduler.Options; -using TakeoutSaaS.Module.Scheduler.Services; - -namespace TakeoutSaaS.Module.Scheduler.Extensions; - -/// -/// 调度模块注册扩展(默认 Hangfire)。 -/// -public static class SchedulerServiceCollectionExtensions -{ - /// - /// 注册调度模块。 - /// - public static IServiceCollection AddSchedulerModule(this IServiceCollection services, IConfiguration configuration) - { - services.AddOptions() - .Bind(configuration.GetSection("Scheduler")) - .ValidateDataAnnotations() - .ValidateOnStart(); - - services.AddOptions() - .Bind(configuration.GetSection("Scheduler:SubscriptionAutomation")) - .ValidateDataAnnotations() - .ValidateOnStart(); - - services.AddOptions() - .Bind(configuration.GetSection("Scheduler:BillingAutomation")) - .ValidateDataAnnotations() - .ValidateOnStart(); - - services.AddHangfire((serviceProvider, config) => - { - var options = serviceProvider.GetRequiredService>().CurrentValue; - config - .UseSimpleAssemblyNameTypeSerializer() - .UseRecommendedSerializerSettings() - .UsePostgreSqlStorage(storage => - { - storage.UseNpgsqlConnection(options.ConnectionString); - }); - }); - - services.AddHangfireServer((serviceProvider, options) => - { - var scheduler = serviceProvider.GetRequiredService>().CurrentValue; - options.WorkerCount = scheduler.WorkerCount ?? options.WorkerCount; - }); - - services.AddSingleton(); - services.AddHostedService(); - - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - - return services; - } - - /// - /// 启用 Hangfire Dashboard(默认关闭,可通过配置开启)。 - /// - public static IApplicationBuilder UseSchedulerDashboard(this IApplicationBuilder app, IConfiguration configuration) - { - var options = configuration.GetSection("Scheduler").Get(); - if (options is { DashboardEnabled: true }) - { - app.UseHangfireDashboard(options.DashboardPath); - } - - return app; - } -} diff --git a/src/Modules/TakeoutSaaS.Module.Scheduler/HostedServices/RecurringJobHostedService.cs b/src/Modules/TakeoutSaaS.Module.Scheduler/HostedServices/RecurringJobHostedService.cs deleted file mode 100644 index b2dca9b..0000000 --- a/src/Modules/TakeoutSaaS.Module.Scheduler/HostedServices/RecurringJobHostedService.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Module.Scheduler.Abstractions; - -namespace TakeoutSaaS.Module.Scheduler.HostedServices; - -/// -/// 启动时注册周期性任务的宿主服务。 -/// -public sealed class RecurringJobHostedService(IRecurringJobRegistrar registrar, ILogger logger) : IHostedService -{ - /// - public async Task StartAsync(CancellationToken cancellationToken) - { - await registrar.RegisterAsync(cancellationToken).ConfigureAwait(false); - logger.LogInformation("调度任务已注册"); - } - - /// - public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; -} diff --git a/src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/BillingOverdueProcessJob.cs b/src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/BillingOverdueProcessJob.cs deleted file mode 100644 index e17a784..0000000 --- a/src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/BillingOverdueProcessJob.cs +++ /dev/null @@ -1,32 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using TakeoutSaaS.Application.App.Billings.Commands; -using TakeoutSaaS.Module.Scheduler.Options; - -namespace TakeoutSaaS.Module.Scheduler.Jobs; - -/// -/// 账单逾期标记任务:将超过到期日的待支付账单标记为逾期。 -/// -public sealed class BillingOverdueProcessJob( - IMediator mediator, - IOptionsMonitor optionsMonitor, - ILogger logger) -{ - /// - /// 执行逾期账单标记。 - /// - public async Task ExecuteAsync() - { - // 1. 读取配置并执行逾期处理 - var options = optionsMonitor.CurrentValue; - var updatedCount = await mediator.Send(new ProcessOverdueBillingsCommand()); - - // 2. 记录执行结果 - logger.LogInformation( - "定时任务:逾期账单标记完成,更新 {UpdatedCount} 条(Cron={Cron})", - updatedCount, - options.OverdueBillingProcessCron); - } -} diff --git a/src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/BusinessStatusAutoSwitchJob.cs b/src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/BusinessStatusAutoSwitchJob.cs deleted file mode 100644 index 30a3924..0000000 --- a/src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/BusinessStatusAutoSwitchJob.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Services; - -namespace TakeoutSaaS.Module.Scheduler.Jobs; - -/// -/// 门店营业状态自动切换任务。 -/// -public sealed class BusinessStatusAutoSwitchJob( - IStoreSchedulerService schedulerService, - ILogger logger) -{ - /// - /// 执行自动切换。 - /// - public async Task ExecuteAsync() - { - // 1. 执行自动切换 - var updated = await schedulerService.AutoSwitchBusinessStatusAsync(DateTime.UtcNow, CancellationToken.None); - - // 2. (空行后) 记录执行结果 - logger.LogInformation("定时任务:门店营业状态自动切换执行完成,更新 {UpdatedCount} 家门店", updated); - } -} diff --git a/src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/CouponExpireJob.cs b/src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/CouponExpireJob.cs deleted file mode 100644 index 294c2da..0000000 --- a/src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/CouponExpireJob.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.Extensions.Logging; - -namespace TakeoutSaaS.Module.Scheduler.Jobs; - -/// -/// 优惠券过期处理任务(占位实现)。 -/// -public sealed class CouponExpireJob(ILogger logger) -{ - /// - /// 执行优惠券过期清理。 - /// - public Task ExecuteAsync() - { - logger.LogInformation("定时任务:处理已过期优惠券(占位实现)"); - return Task.CompletedTask; - } -} diff --git a/src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/LogCleanupJob.cs b/src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/LogCleanupJob.cs deleted file mode 100644 index aa67c70..0000000 --- a/src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/LogCleanupJob.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.Extensions.Logging; - -namespace TakeoutSaaS.Module.Scheduler.Jobs; - -/// -/// 日志清理任务(占位实现)。 -/// -public sealed class LogCleanupJob(ILogger logger) -{ - /// - /// 执行日志清理。 - /// - public Task ExecuteAsync() - { - logger.LogInformation("定时任务:清理历史日志(占位实现)"); - return Task.CompletedTask; - } -} diff --git a/src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/OrderTimeoutJob.cs b/src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/OrderTimeoutJob.cs deleted file mode 100644 index 80d7513..0000000 --- a/src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/OrderTimeoutJob.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.Extensions.Logging; - -namespace TakeoutSaaS.Module.Scheduler.Jobs; - -/// -/// 订单超时取消任务(占位,后续接入订单服务)。 -/// -public sealed class OrderTimeoutJob(ILogger logger) -{ - /// - /// 执行超时订单检查。 - /// - public Task ExecuteAsync() - { - logger.LogInformation("定时任务:检查超时未支付订单并取消(占位实现)"); - return Task.CompletedTask; - } -} diff --git a/src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/QualificationExpiryCheckJob.cs b/src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/QualificationExpiryCheckJob.cs deleted file mode 100644 index 94ff168..0000000 --- a/src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/QualificationExpiryCheckJob.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Microsoft.Extensions.Logging; -using TakeoutSaaS.Application.App.Stores.Services; - -namespace TakeoutSaaS.Module.Scheduler.Jobs; - -/// -/// 门店资质过期检查任务。 -/// -public sealed class QualificationExpiryCheckJob( - IStoreSchedulerService schedulerService, - ILogger logger) -{ - /// - /// 执行资质过期检查。 - /// - public async Task ExecuteAsync() - { - // 1. 执行资质过期检查 - var updated = await schedulerService.CheckQualificationExpiryAsync(DateTime.UtcNow, CancellationToken.None); - - // 2. (空行后) 记录执行结果 - logger.LogInformation("定时任务:门店资质过期检查执行完成,更新 {UpdatedCount} 家门店", updated); - } -} diff --git a/src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/SubscriptionAutoRenewalJob.cs b/src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/SubscriptionAutoRenewalJob.cs deleted file mode 100644 index 3a285ca..0000000 --- a/src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/SubscriptionAutoRenewalJob.cs +++ /dev/null @@ -1,70 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using TakeoutSaaS.Application.App.Subscriptions.Commands; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Module.Scheduler.Options; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Module.Scheduler.Jobs; - -/// -/// 订阅自动续费任务:为即将到期且开启自动续费的订阅生成续费账单。 -/// -public sealed class SubscriptionAutoRenewalJob( - IMediator mediator, - ITenantRepository tenantRepository, - ITenantContextAccessor tenantContextAccessor, - IOptionsMonitor optionsMonitor, - ILogger logger) -{ - /// - /// 执行自动续费账单生成。 - /// - public async Task ExecuteAsync() - { - // 1. 读取配置 - var options = optionsMonitor.CurrentValue; - - // 2. (空行后) 获取需要处理的租户列表(排除系统租户) - var tenants = await tenantRepository.SearchAsync(null, null, CancellationToken.None); - var targets = tenants.Where(x => x.Id > 0).ToList(); - - // 3. (空行后) 按租户逐个执行自动续费 - var candidateCount = 0; - var createdBillCount = 0; - var previousContext = tenantContextAccessor.Current; - try - { - foreach (var tenant in targets) - { - tenantContextAccessor.Current = new TenantContext(tenant.Id, tenant.Code, "scheduler"); - try - { - var result = await mediator.Send(new ProcessAutoRenewalCommand - { - RenewalDaysBeforeExpiry = options.AutoRenewalDaysBeforeExpiry - }); - - candidateCount += result.CandidateCount; - createdBillCount += result.CreatedBillCount; - } - catch (Exception ex) - { - logger.LogError(ex, "定时任务:自动续费执行失败 TenantId={TenantId}", tenant.Id); - } - } - } - finally - { - tenantContextAccessor.Current = previousContext; - } - - // 4. (空行后) 记录执行结果 - logger.LogInformation( - "定时任务:自动续费处理完成,处理租户 {TenantCount},候选 {CandidateCount},创建账单 {CreatedBillCount}", - targets.Count, - candidateCount, - createdBillCount); - } -} diff --git a/src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/SubscriptionExpiryCheckJob.cs b/src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/SubscriptionExpiryCheckJob.cs deleted file mode 100644 index b0ca568..0000000 --- a/src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/SubscriptionExpiryCheckJob.cs +++ /dev/null @@ -1,70 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using TakeoutSaaS.Application.App.Subscriptions.Commands; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Module.Scheduler.Options; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Module.Scheduler.Jobs; - -/// -/// 订阅到期检查任务:到期进入宽限期,宽限期到期自动暂停。 -/// -public sealed class SubscriptionExpiryCheckJob( - IMediator mediator, - ITenantRepository tenantRepository, - ITenantContextAccessor tenantContextAccessor, - IOptionsMonitor optionsMonitor, - ILogger logger) -{ - /// - /// 执行订阅到期检查。 - /// - public async Task ExecuteAsync() - { - // 1. 读取配置 - var options = optionsMonitor.CurrentValue; - - // 2. (空行后) 获取需要处理的租户列表(排除系统租户) - var tenants = await tenantRepository.SearchAsync(null, null, CancellationToken.None); - var targets = tenants.Where(x => x.Id > 0).ToList(); - - // 3. (空行后) 按租户逐个执行到期处理 - var enteredGracePeriodCount = 0; - var suspendedCount = 0; - var previousContext = tenantContextAccessor.Current; - try - { - foreach (var tenant in targets) - { - tenantContextAccessor.Current = new TenantContext(tenant.Id, tenant.Code, "scheduler"); - try - { - var result = await mediator.Send(new ProcessSubscriptionExpiryCommand - { - GracePeriodDays = options.GracePeriodDays - }); - - enteredGracePeriodCount += result.EnteredGracePeriodCount; - suspendedCount += result.SuspendedCount; - } - catch (Exception ex) - { - logger.LogError(ex, "定时任务:订阅到期检查执行失败 TenantId={TenantId}", tenant.Id); - } - } - } - finally - { - tenantContextAccessor.Current = previousContext; - } - - // 4. (空行后) 记录执行结果 - logger.LogInformation( - "定时任务:订阅到期检查完成,处理租户 {TenantCount},进入宽限期 {EnteredGracePeriodCount},暂停 {SuspendedCount}", - targets.Count, - enteredGracePeriodCount, - suspendedCount); - } -} diff --git a/src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/SubscriptionRenewalReminderJob.cs b/src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/SubscriptionRenewalReminderJob.cs deleted file mode 100644 index d3e284d..0000000 --- a/src/Modules/TakeoutSaaS.Module.Scheduler/Jobs/SubscriptionRenewalReminderJob.cs +++ /dev/null @@ -1,70 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using TakeoutSaaS.Application.App.Subscriptions.Commands; -using TakeoutSaaS.Domain.Tenants.Repositories; -using TakeoutSaaS.Module.Scheduler.Options; -using TakeoutSaaS.Shared.Abstractions.Tenancy; - -namespace TakeoutSaaS.Module.Scheduler.Jobs; - -/// -/// 订阅续费提醒任务:到期前 7/3/1 天发送站内提醒。 -/// -public sealed class SubscriptionRenewalReminderJob( - IMediator mediator, - ITenantRepository tenantRepository, - ITenantContextAccessor tenantContextAccessor, - IOptionsMonitor optionsMonitor, - ILogger logger) -{ - /// - /// 执行续费提醒扫描与发送。 - /// - public async Task ExecuteAsync() - { - // 1. 读取配置 - var options = optionsMonitor.CurrentValue; - - // 2. (空行后) 获取需要处理的租户列表(排除系统租户) - var tenants = await tenantRepository.SearchAsync(null, null, CancellationToken.None); - var targets = tenants.Where(x => x.Id > 0).ToList(); - - // 3. (空行后) 按租户逐个执行续费提醒 - var candidateCount = 0; - var createdReminderCount = 0; - var previousContext = tenantContextAccessor.Current; - try - { - foreach (var tenant in targets) - { - tenantContextAccessor.Current = new TenantContext(tenant.Id, tenant.Code, "scheduler"); - try - { - var result = await mediator.Send(new ProcessRenewalRemindersCommand - { - ReminderDaysBeforeExpiry = options.ReminderDaysBeforeExpiry - }); - - candidateCount += result.CandidateCount; - createdReminderCount += result.CreatedReminderCount; - } - catch (Exception ex) - { - logger.LogError(ex, "定时任务:续费提醒执行失败 TenantId={TenantId}", tenant.Id); - } - } - } - finally - { - tenantContextAccessor.Current = previousContext; - } - - // 4. (空行后) 记录执行结果 - logger.LogInformation( - "定时任务:续费提醒处理完成,处理租户 {TenantCount},候选 {CandidateCount},创建 {CreatedReminderCount}", - targets.Count, - candidateCount, - createdReminderCount); - } -} diff --git a/src/Modules/TakeoutSaaS.Module.Scheduler/Options/BillingAutomationOptions.cs b/src/Modules/TakeoutSaaS.Module.Scheduler/Options/BillingAutomationOptions.cs deleted file mode 100644 index 2ced3bc..0000000 --- a/src/Modules/TakeoutSaaS.Module.Scheduler/Options/BillingAutomationOptions.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Module.Scheduler.Options; - -/// -/// 账单自动化相关配置(逾期标记等)。 -/// -public sealed class BillingAutomationOptions -{ - /// - /// 逾期账单标记任务 Cron 表达式(Hangfire)。 - /// 默认每 10 分钟执行一次。 - /// - [Required] - public string OverdueBillingProcessCron { get; set; } = "*/10 * * * *"; -} diff --git a/src/Modules/TakeoutSaaS.Module.Scheduler/Options/SchedulerOptions.cs b/src/Modules/TakeoutSaaS.Module.Scheduler/Options/SchedulerOptions.cs deleted file mode 100644 index 880790c..0000000 --- a/src/Modules/TakeoutSaaS.Module.Scheduler/Options/SchedulerOptions.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Module.Scheduler.Options; - -/// -/// 调度模块配置。 -/// -public sealed class SchedulerOptions -{ - /// - /// Hangfire 存储使用的连接字符串。 - /// - [Required] - public string ConnectionString { get; set; } = string.Empty; - - /// - /// 工作线程数,默认根据 CPU 计算。 - /// - [Range(1, 100)] - public int? WorkerCount { get; set; } - - /// - /// 是否启用 Dashboard(默认 false,待 AdminUI 接入)。 - /// - public bool DashboardEnabled { get; set; } - - /// - /// Dashboard 路径。 - /// - public string DashboardPath { get; set; } = "/hangfire"; -} diff --git a/src/Modules/TakeoutSaaS.Module.Scheduler/Options/SubscriptionAutomationOptions.cs b/src/Modules/TakeoutSaaS.Module.Scheduler/Options/SubscriptionAutomationOptions.cs deleted file mode 100644 index 91e1601..0000000 --- a/src/Modules/TakeoutSaaS.Module.Scheduler/Options/SubscriptionAutomationOptions.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Module.Scheduler.Options; - -/// -/// 订阅自动化相关配置(续费提醒、自动续费、宽限期处理)。 -/// -public sealed class SubscriptionAutomationOptions -{ - /// - /// 自动续费任务执行小时(UTC)。 - /// - [Range(0, 23)] - public int AutoRenewalExecuteHourUtc { get; set; } = 1; - - /// - /// 自动续费:到期前 N 天生成续费账单。 - /// - [Range(0, 365)] - public int AutoRenewalDaysBeforeExpiry { get; set; } = 3; - - /// - /// 续费提醒任务执行小时(UTC)。 - /// - [Range(0, 23)] - public int RenewalReminderExecuteHourUtc { get; set; } = 10; - - /// - /// 续费提醒:到期前 N 天发送提醒。 - /// - [MinLength(1)] - public int[] ReminderDaysBeforeExpiry { get; set; } = [7, 3, 1]; - - /// - /// 订阅到期检查任务执行小时(UTC)。 - /// - [Range(0, 23)] - public int SubscriptionExpiryCheckExecuteHourUtc { get; set; } = 2; - - /// - /// 宽限期天数。 - /// - [Range(0, 365)] - public int GracePeriodDays { get; set; } = 7; -} - diff --git a/src/Modules/TakeoutSaaS.Module.Scheduler/Services/RecurringJobRegistrar.cs b/src/Modules/TakeoutSaaS.Module.Scheduler/Services/RecurringJobRegistrar.cs deleted file mode 100644 index 5d65dc3..0000000 --- a/src/Modules/TakeoutSaaS.Module.Scheduler/Services/RecurringJobRegistrar.cs +++ /dev/null @@ -1,59 +0,0 @@ -using Hangfire; -using Microsoft.Extensions.Options; -using TakeoutSaaS.Module.Scheduler.Abstractions; -using TakeoutSaaS.Module.Scheduler.Jobs; -using TakeoutSaaS.Module.Scheduler.Options; - -namespace TakeoutSaaS.Module.Scheduler.Services; - -/// -/// 周期性任务注册器。 -/// -public sealed class RecurringJobRegistrar( - IOptionsMonitor subscriptionAutomationOptions, - IOptionsMonitor billingAutomationOptions) - : IRecurringJobRegistrar -{ - /// - public Task RegisterAsync(CancellationToken cancellationToken = default) - { - // 1. 业务占位任务(示例) - RecurringJob.AddOrUpdate("orders.timeout-cancel", job => job.ExecuteAsync(), "*/5 * * * *"); - RecurringJob.AddOrUpdate("coupons.expire", job => job.ExecuteAsync(), "0 */1 * * *"); - RecurringJob.AddOrUpdate("logs.cleanup", job => job.ExecuteAsync(), "0 3 * * *"); - - // 2. 订阅自动化任务(自动续费、续费提醒、到期进入宽限期) - var options = subscriptionAutomationOptions.CurrentValue; - RecurringJob.AddOrUpdate( - "subscriptions.auto-renewal", - job => job.ExecuteAsync(), - $"0 {options.AutoRenewalExecuteHourUtc} * * *"); - RecurringJob.AddOrUpdate( - "subscriptions.renewal-reminder", - job => job.ExecuteAsync(), - $"0 {options.RenewalReminderExecuteHourUtc} * * *"); - RecurringJob.AddOrUpdate( - "subscriptions.expiry-check", - job => job.ExecuteAsync(), - $"0 {options.SubscriptionExpiryCheckExecuteHourUtc} * * *"); - - // 3. 账单自动化任务(逾期标记) - var billingOptions = billingAutomationOptions.CurrentValue; - RecurringJob.AddOrUpdate( - "billings.overdue-process", - job => job.ExecuteAsync(), - billingOptions.OverdueBillingProcessCron); - - // 4. (空行后) 门店管理自动化任务 - RecurringJob.AddOrUpdate( - "stores.business-status-auto-switch", - job => job.ExecuteAsync(), - "*/1 * * * *"); - RecurringJob.AddOrUpdate( - "stores.qualification-expiry-check", - job => job.ExecuteAsync(), - "0 2 * * *"); - - return Task.CompletedTask; - } -} diff --git a/src/Modules/TakeoutSaaS.Module.Sms/Abstractions/ISmsSender.cs b/src/Modules/TakeoutSaaS.Module.Sms/Abstractions/ISmsSender.cs deleted file mode 100644 index 01380db..0000000 --- a/src/Modules/TakeoutSaaS.Module.Sms/Abstractions/ISmsSender.cs +++ /dev/null @@ -1,19 +0,0 @@ -using TakeoutSaaS.Module.Sms.Models; - -namespace TakeoutSaaS.Module.Sms.Abstractions; - -/// -/// 短信发送抽象。 -/// -public interface ISmsSender -{ - /// - /// 服务商类型。 - /// - SmsProviderKind Provider { get; } - - /// - /// 发送短信。 - /// - Task SendAsync(SmsSendRequest request, CancellationToken cancellationToken = default); -} diff --git a/src/Modules/TakeoutSaaS.Module.Sms/Abstractions/ISmsSenderResolver.cs b/src/Modules/TakeoutSaaS.Module.Sms/Abstractions/ISmsSenderResolver.cs deleted file mode 100644 index f3385d2..0000000 --- a/src/Modules/TakeoutSaaS.Module.Sms/Abstractions/ISmsSenderResolver.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace TakeoutSaaS.Module.Sms.Abstractions; - -/// -/// 短信服务商解析器。 -/// -public interface ISmsSenderResolver -{ - /// - /// 获取指定服务商的发送器。 - /// - ISmsSender Resolve(SmsProviderKind? provider = null); -} diff --git a/src/Modules/TakeoutSaaS.Module.Sms/Extensions/SmsServiceCollectionExtensions.cs b/src/Modules/TakeoutSaaS.Module.Sms/Extensions/SmsServiceCollectionExtensions.cs deleted file mode 100644 index 651c143..0000000 --- a/src/Modules/TakeoutSaaS.Module.Sms/Extensions/SmsServiceCollectionExtensions.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using TakeoutSaaS.Module.Sms.Abstractions; -using TakeoutSaaS.Module.Sms.Options; -using TakeoutSaaS.Module.Sms.Services; - -namespace TakeoutSaaS.Module.Sms.Extensions; - -/// -/// 短信模块 DI 注册扩展。 -/// -public static class SmsServiceCollectionExtensions -{ - /// - /// 注册短信模块(包含腾讯云、阿里云实现)。 - /// - public static IServiceCollection AddSmsModule(this IServiceCollection services, IConfiguration configuration) - { - services.AddOptions() - .Bind(configuration.GetSection("Sms")) - .ValidateDataAnnotations() - .ValidateOnStart(); - - services.AddHttpClient(nameof(TencentSmsSender)); - services.AddHttpClient(nameof(AliyunSmsSender)); - - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - - return services; - } -} diff --git a/src/Modules/TakeoutSaaS.Module.Sms/Models/SmsSendRequest.cs b/src/Modules/TakeoutSaaS.Module.Sms/Models/SmsSendRequest.cs deleted file mode 100644 index fe3b333..0000000 --- a/src/Modules/TakeoutSaaS.Module.Sms/Models/SmsSendRequest.cs +++ /dev/null @@ -1,42 +0,0 @@ -namespace TakeoutSaaS.Module.Sms.Models; - -/// -/// 短信发送请求。 -/// -public sealed class SmsSendRequest -{ - /// - /// 初始化短信发送请求。 - /// - /// 目标手机号码(含国家码,如 +86xxxxxxxxxxx)。 - /// 模版编号。 - /// 模版变量。 - /// 短信签名。 - public SmsSendRequest(string phoneNumber, string templateCode, IDictionary variables, string? signName = null) - { - PhoneNumber = phoneNumber; - TemplateCode = templateCode; - Variables = new Dictionary(variables); - SignName = signName; - } - - /// - /// 目标手机号。 - /// - public string PhoneNumber { get; } - - /// - /// 模版编号。 - /// - public string TemplateCode { get; } - - /// - /// 模版变量。 - /// - public IReadOnlyDictionary Variables { get; } - - /// - /// 可选的签名。 - /// - public string? SignName { get; } -} diff --git a/src/Modules/TakeoutSaaS.Module.Sms/Models/SmsSendResult.cs b/src/Modules/TakeoutSaaS.Module.Sms/Models/SmsSendResult.cs deleted file mode 100644 index dfdd69f..0000000 --- a/src/Modules/TakeoutSaaS.Module.Sms/Models/SmsSendResult.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace TakeoutSaaS.Module.Sms.Models; - -/// -/// 短信发送结果。 -/// -public sealed class SmsSendResult -{ - /// - /// 是否发送成功。 - /// - public bool Success { get; init; } - - /// - /// 服务商返回的请求标识。 - /// - public string? RequestId { get; init; } - - /// - /// 描述信息。 - /// - public string? Message { get; init; } -} diff --git a/src/Modules/TakeoutSaaS.Module.Sms/Options/AliyunSmsOptions.cs b/src/Modules/TakeoutSaaS.Module.Sms/Options/AliyunSmsOptions.cs deleted file mode 100644 index cfa09b1..0000000 --- a/src/Modules/TakeoutSaaS.Module.Sms/Options/AliyunSmsOptions.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Module.Sms.Options; - -/// -/// 阿里云短信配置。 -/// -public sealed class AliyunSmsOptions -{ - /// - /// AccessKeyId。 - /// - [Required] - public string AccessKeyId { get; set; } = string.Empty; - - /// - /// AccessKeySecret。 - /// - [Required] - public string AccessKeySecret { get; set; } = string.Empty; - - /// - /// 短信服务域名。 - /// - public string Endpoint { get; set; } = "dysmsapi.aliyuncs.com"; - - /// - /// 默认签名。 - /// - public string? SignName { get; set; } - - /// - /// 地域 ID。 - /// - public string Region { get; set; } = "cn-hangzhou"; -} diff --git a/src/Modules/TakeoutSaaS.Module.Sms/Options/SmsOptions.cs b/src/Modules/TakeoutSaaS.Module.Sms/Options/SmsOptions.cs deleted file mode 100644 index 32c3ada..0000000 --- a/src/Modules/TakeoutSaaS.Module.Sms/Options/SmsOptions.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Module.Sms.Options; - -/// -/// 短信模块配置。 -/// -public sealed class SmsOptions -{ - /// - /// 默认服务商,默认为腾讯云。 - /// - public SmsProviderKind Provider { get; set; } = SmsProviderKind.Tencent; - - /// - /// 默认签名。 - /// - public string? DefaultSignName { get; set; } - - /// - /// 是否启用模拟发送(仅日志,不实际调用),方便开发环境。 - /// - public bool UseMock { get; set; } - - /// - /// 腾讯云短信配置。 - /// - [Required] - public TencentSmsOptions Tencent { get; set; } = new(); - - /// - /// 阿里云短信配置。 - /// - [Required] - public AliyunSmsOptions Aliyun { get; set; } = new(); - - /// - /// 场景与模板映射(如 login: TEMPLATE_ID)。 - /// - public Dictionary SceneTemplates { get; set; } = new(StringComparer.OrdinalIgnoreCase); -} diff --git a/src/Modules/TakeoutSaaS.Module.Sms/Options/TencentSmsOptions.cs b/src/Modules/TakeoutSaaS.Module.Sms/Options/TencentSmsOptions.cs deleted file mode 100644 index 3e02bd4..0000000 --- a/src/Modules/TakeoutSaaS.Module.Sms/Options/TencentSmsOptions.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Module.Sms.Options; - -/// -/// 腾讯云短信配置。 -/// -public sealed class TencentSmsOptions -{ - /// - /// SecretId。 - /// - [Required] - public string SecretId { get; set; } = string.Empty; - - /// - /// SecretKey。 - /// - [Required] - public string SecretKey { get; set; } = string.Empty; - - /// - /// 应用 SdkAppId。 - /// - [Required] - public string SdkAppId { get; set; } = string.Empty; - - /// - /// 默认签名。 - /// - public string? SignName { get; set; } - - /// - /// 默认地域。 - /// - public string Region { get; set; } = "ap-guangzhou"; - - /// - /// 接口域名。 - /// - public string Endpoint { get; set; } = "https://sms.tencentcloudapi.com"; -} diff --git a/src/Modules/TakeoutSaaS.Module.Sms/Services/AliyunSmsSender.cs b/src/Modules/TakeoutSaaS.Module.Sms/Services/AliyunSmsSender.cs deleted file mode 100644 index 213cfa0..0000000 --- a/src/Modules/TakeoutSaaS.Module.Sms/Services/AliyunSmsSender.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using TakeoutSaaS.Module.Sms.Abstractions; -using TakeoutSaaS.Module.Sms.Models; -using TakeoutSaaS.Module.Sms.Options; - -namespace TakeoutSaaS.Module.Sms.Services; - -/// -/// 阿里云短信发送实现(简化版,占位可扩展正式签名流程)。 -/// -public sealed class AliyunSmsSender(IHttpClientFactory httpClientFactory, IOptionsMonitor optionsMonitor, ILogger logger) - : ISmsSender -{ - /// - public SmsProviderKind Provider => SmsProviderKind.Aliyun; - - /// - public Task SendAsync(SmsSendRequest request, CancellationToken cancellationToken = default) - { - var options = optionsMonitor.CurrentValue; - if (options.UseMock) - { - logger.LogInformation("Mock 发送阿里云短信到 {Phone}, Template:{Template}", request.PhoneNumber, request.TemplateCode); - return Task.FromResult(new SmsSendResult { Success = true, Message = "Mocked" }); - } - // 预留 HttpClient,便于后续接入阿里云正式签名请求 - using var httpClient = httpClientFactory.CreateClient(nameof(AliyunSmsSender)); - - // 占位:保留待接入阿里云正式签名流程,当前返回未实现。 - logger.LogWarning("阿里云短信尚未启用,请配置腾讯云或开启 UseMock。"); - return Task.FromResult(new SmsSendResult { Success = false, Message = "Aliyun SMS not enabled" }); - } -} diff --git a/src/Modules/TakeoutSaaS.Module.Sms/Services/SmsSenderResolver.cs b/src/Modules/TakeoutSaaS.Module.Sms/Services/SmsSenderResolver.cs deleted file mode 100644 index 2d5906b..0000000 --- a/src/Modules/TakeoutSaaS.Module.Sms/Services/SmsSenderResolver.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Microsoft.Extensions.Options; -using TakeoutSaaS.Module.Sms.Abstractions; -using TakeoutSaaS.Module.Sms.Options; - -namespace TakeoutSaaS.Module.Sms.Services; - -/// -/// 短信服务商解析器。 -/// -public sealed class SmsSenderResolver(IOptionsMonitor optionsMonitor, IEnumerable senders) : ISmsSenderResolver -{ - private readonly IReadOnlyDictionary _map = senders.ToDictionary(x => x.Provider); - - /// - public ISmsSender Resolve(SmsProviderKind? provider = null) - { - var key = provider ?? optionsMonitor.CurrentValue.Provider; - if (_map.TryGetValue(key, out var sender)) - { - return sender; - } - - throw new InvalidOperationException($"未注册短信服务商:{key}"); - } -} diff --git a/src/Modules/TakeoutSaaS.Module.Sms/Services/TencentSmsSender.cs b/src/Modules/TakeoutSaaS.Module.Sms/Services/TencentSmsSender.cs deleted file mode 100644 index ee14a8f..0000000 --- a/src/Modules/TakeoutSaaS.Module.Sms/Services/TencentSmsSender.cs +++ /dev/null @@ -1,140 +0,0 @@ -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using System.Globalization; -using System.Security.Cryptography; -using System.Text; -using System.Text.Json; -using TakeoutSaaS.Module.Sms.Abstractions; -using TakeoutSaaS.Module.Sms.Models; -using TakeoutSaaS.Module.Sms.Options; - -namespace TakeoutSaaS.Module.Sms.Services; - -/// -/// 腾讯云短信发送实现(TC3-HMAC 签名)。 -/// -public sealed class TencentSmsSender(IHttpClientFactory httpClientFactory, IOptionsMonitor optionsMonitor, ILogger logger) - : ISmsSender -{ - private const string Service = "sms"; - private const string Action = "SendSms"; - private const string Version = "2021-01-11"; - - /// - public SmsProviderKind Provider => SmsProviderKind.Tencent; - - /// - public async Task SendAsync(SmsSendRequest request, CancellationToken cancellationToken = default) - { - // 1. 读取配置并处理 Mock - var options = optionsMonitor.CurrentValue; - if (options.UseMock) - { - logger.LogInformation("Mock 发送短信到 {Phone}, Template:{Template}, Vars:{Vars}", request.PhoneNumber, request.TemplateCode, JsonSerializer.Serialize(request.Variables)); - return new SmsSendResult { Success = true, Message = "Mocked" }; - } - - // 2. 构建请求负载与签名所需字段 - var tencent = options.Tencent; - var payload = BuildPayload(request, tencent); - var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); - var date = DateTimeOffset.FromUnixTimeSeconds(timestamp).UtcDateTime.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture); - - var host = new Uri(tencent.Endpoint).Host; - var canonicalRequest = BuildCanonicalRequest(payload, host, tencent.Endpoint.StartsWith("https", StringComparison.OrdinalIgnoreCase)); - var stringToSign = BuildStringToSign(canonicalRequest, timestamp, date); - var signature = Sign(stringToSign, tencent.SecretKey, date); - - // 3. 构建 HTTP 请求 - using var httpClient = httpClientFactory.CreateClient(nameof(TencentSmsSender)); - using var httpRequest = new HttpRequestMessage(HttpMethod.Post, tencent.Endpoint) - { - Content = new StringContent(payload, Encoding.UTF8, "application/json") - }; - - httpRequest.Headers.Add("Host", host); - httpRequest.Headers.Add("X-TC-Action", Action); - httpRequest.Headers.Add("X-TC-Version", Version); - httpRequest.Headers.Add("X-TC-Timestamp", timestamp.ToString(CultureInfo.InvariantCulture)); - httpRequest.Headers.Add("X-TC-Region", tencent.Region); - httpRequest.Headers.Add("Authorization", - $"TC3-HMAC-SHA256 Credential={tencent.SecretId}/{date}/{Service}/tc3_request, SignedHeaders=content-type;host, Signature={signature}"); - - // 4. 发送请求并读取响应 - var response = await httpClient.SendAsync(httpRequest, cancellationToken).ConfigureAwait(false); - var content = await response.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(false); - - if (!response.IsSuccessStatusCode) - { - logger.LogWarning("腾讯云短信发送失败:{Status} {Content}", response.StatusCode, content); - return new SmsSendResult { Success = false, Message = content }; - } - - // 5. 解析响应 - using var doc = JsonDocument.Parse(content); - var root = doc.RootElement.GetProperty("Response"); - var status = root.GetProperty("SendStatusSet")[0]; - var code = status.GetProperty("Code").GetString(); - var message = status.GetProperty("Message").GetString(); - var requestId = root.GetProperty("RequestId").GetString(); - - var success = string.Equals(code, "Ok", StringComparison.OrdinalIgnoreCase); - return new SmsSendResult - { - Success = success, - RequestId = requestId, - Message = message - }; - } - - private static string BuildPayload(SmsSendRequest request, TencentSmsOptions options) - { - var payload = new - { - PhoneNumberSet = new[] { request.PhoneNumber }, - SmsSdkAppId = options.SdkAppId, - SignName = request.SignName ?? options.SignName, - TemplateId = request.TemplateCode, - TemplateParamSet = request.Variables.Values.ToArray() - }; - - return JsonSerializer.Serialize(payload); - } - - private static string BuildCanonicalRequest(string payload, string host, bool useHttps) - { - _ = useHttps; - var hashedPayload = HashSha256(payload); - var canonicalHeaders = $"content-type:application/json\nhost:{host}\n"; - return $"POST\n/\n\n{canonicalHeaders}\ncontent-type;host\n{hashedPayload}"; - } - - private static string BuildStringToSign(string canonicalRequest, long timestamp, string date) - { - var hashedRequest = HashSha256(canonicalRequest); - return $"TC3-HMAC-SHA256\n{timestamp}\n{date}/{Service}/tc3_request\n{hashedRequest}"; - } - - private static string Sign(string stringToSign, string secretKey, string date) - { - static byte[] HmacSha256(byte[] key, string msg) => new HMACSHA256(key).ComputeHash(Encoding.UTF8.GetBytes(msg)); - - var secretDate = HmacSha256(Encoding.UTF8.GetBytes($"TC3{secretKey}"), date); - var secretService = HmacSha256(secretDate, Service); - var secretSigning = HmacSha256(secretService, "tc3_request"); - var signatureBytes = new HMACSHA256(secretSigning).ComputeHash(Encoding.UTF8.GetBytes(stringToSign)); - return Convert.ToHexString(signatureBytes).ToLowerInvariant(); - } - - private static string HashSha256(string raw) - { - var bytes = SHA256.HashData(Encoding.UTF8.GetBytes(raw)); - var builder = new StringBuilder(bytes.Length * 2); - foreach (var b in bytes) - { - builder.Append(b.ToString("x2", CultureInfo.InvariantCulture)); - } - - return builder.ToString(); - } -} diff --git a/src/Modules/TakeoutSaaS.Module.Sms/SmsProviderKind.cs b/src/Modules/TakeoutSaaS.Module.Sms/SmsProviderKind.cs deleted file mode 100644 index e374d12..0000000 --- a/src/Modules/TakeoutSaaS.Module.Sms/SmsProviderKind.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace TakeoutSaaS.Module.Sms; - -/// -/// 短信服务商类型。 -/// -public enum SmsProviderKind -{ - /// - /// 腾讯云短信。 - /// - Tencent = 1, - - /// - /// 阿里云短信。 - /// - Aliyun = 2 -} diff --git a/src/Modules/TakeoutSaaS.Module.Storage/Abstractions/IObjectStorageProvider.cs b/src/Modules/TakeoutSaaS.Module.Storage/Abstractions/IObjectStorageProvider.cs deleted file mode 100644 index 41b6e31..0000000 --- a/src/Modules/TakeoutSaaS.Module.Storage/Abstractions/IObjectStorageProvider.cs +++ /dev/null @@ -1,34 +0,0 @@ -using TakeoutSaaS.Module.Storage.Models; - -namespace TakeoutSaaS.Module.Storage.Abstractions; - -/// -/// 对象存储提供商统一抽象。 -/// -public interface IObjectStorageProvider -{ - /// - /// 当前提供商类型。 - /// - StorageProviderKind Kind { get; } - - /// - /// 上传文件到对象存储。 - /// - Task UploadAsync(StorageUploadRequest request, CancellationToken cancellationToken = default); - - /// - /// 生成预签名直传参数(PUT 或表单直传)。 - /// - Task CreateDirectUploadAsync(StorageDirectUploadRequest request, CancellationToken cancellationToken = default); - - /// - /// 生成带过期时间的访问链接。 - /// - Task GenerateDownloadUrlAsync(string objectKey, TimeSpan expires, CancellationToken cancellationToken = default); - - /// - /// 生成公共访问地址(可结合 CDN)。 - /// - string BuildPublicUrl(string objectKey); -} diff --git a/src/Modules/TakeoutSaaS.Module.Storage/Abstractions/IStorageProviderResolver.cs b/src/Modules/TakeoutSaaS.Module.Storage/Abstractions/IStorageProviderResolver.cs deleted file mode 100644 index 63ae4cb..0000000 --- a/src/Modules/TakeoutSaaS.Module.Storage/Abstractions/IStorageProviderResolver.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace TakeoutSaaS.Module.Storage.Abstractions; - -/// -/// 存储提供商解析器,用于按需选择具体实现。 -/// -public interface IStorageProviderResolver -{ - /// - /// 根据配置解析出可用的存储提供商。 - /// - /// 目标提供商类型,空则使用默认配置。 - /// 对应的存储提供商。 - IObjectStorageProvider Resolve(StorageProviderKind? provider = null); -} diff --git a/src/Modules/TakeoutSaaS.Module.Storage/Extensions/StorageServiceCollectionExtensions.cs b/src/Modules/TakeoutSaaS.Module.Storage/Extensions/StorageServiceCollectionExtensions.cs deleted file mode 100644 index e1972f1..0000000 --- a/src/Modules/TakeoutSaaS.Module.Storage/Extensions/StorageServiceCollectionExtensions.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using TakeoutSaaS.Module.Storage.Abstractions; -using TakeoutSaaS.Module.Storage.Options; -using TakeoutSaaS.Module.Storage.Providers; -using TakeoutSaaS.Module.Storage.Services; - -namespace TakeoutSaaS.Module.Storage.Extensions; - -/// -/// 存储模块服务注册扩展。 -/// -public static class StorageServiceCollectionExtensions -{ - /// - /// 注册存储模块所需的提供商与配置。 - /// - /// 服务集合。 - /// 配置源。 - public static IServiceCollection AddStorageModule(this IServiceCollection services, IConfiguration configuration) - { - services.AddOptions() - .Bind(configuration.GetSection("Storage")) - .ValidateDataAnnotations() - .ValidateOnStart(); - - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - - return services; - } -} diff --git a/src/Modules/TakeoutSaaS.Module.Storage/Models/StorageDirectUploadRequest.cs b/src/Modules/TakeoutSaaS.Module.Storage/Models/StorageDirectUploadRequest.cs deleted file mode 100644 index 201e394..0000000 --- a/src/Modules/TakeoutSaaS.Module.Storage/Models/StorageDirectUploadRequest.cs +++ /dev/null @@ -1,34 +0,0 @@ -namespace TakeoutSaaS.Module.Storage.Models; - -/// -/// 直传(预签名上传)请求参数。 -/// -/// -/// 初始化请求。 -/// -/// 对象键。 -/// 内容类型。 -/// 内容长度。 -/// 签名有效期。 -public sealed class StorageDirectUploadRequest(string objectKey, string contentType, long contentLength, TimeSpan expires) -{ - /// - /// 目标对象键。 - /// - public string ObjectKey { get; } = objectKey; - - /// - /// 内容类型。 - /// - public string ContentType { get; } = contentType; - - /// - /// 内容长度。 - /// - public long ContentLength { get; } = contentLength; - - /// - /// 签名有效期。 - /// - public TimeSpan Expires { get; } = expires; -} diff --git a/src/Modules/TakeoutSaaS.Module.Storage/Models/StorageDirectUploadResult.cs b/src/Modules/TakeoutSaaS.Module.Storage/Models/StorageDirectUploadResult.cs deleted file mode 100644 index 15d11dd..0000000 --- a/src/Modules/TakeoutSaaS.Module.Storage/Models/StorageDirectUploadResult.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace TakeoutSaaS.Module.Storage.Models; - -/// -/// 直传(预签名上传)结果。 -/// -public sealed class StorageDirectUploadResult -{ - /// - /// 预签名上传地址(PUT 上传或表单地址)。 - /// - public string UploadUrl { get; init; } = string.Empty; - - /// - /// 直传附加字段(如表单直传所需字段),PUT 方式为空。 - /// - public IReadOnlyDictionary FormFields { get; init; } = new Dictionary(); - - /// - /// 预签名过期时间。 - /// - public DateTimeOffset ExpiresAt { get; init; } - - /// - /// 关联的对象键。 - /// - public string ObjectKey { get; init; } = string.Empty; - - /// - /// 上传成功后可选的签名下载地址。 - /// - public string? SignedDownloadUrl { get; init; } -} diff --git a/src/Modules/TakeoutSaaS.Module.Storage/Models/StorageUploadRequest.cs b/src/Modules/TakeoutSaaS.Module.Storage/Models/StorageUploadRequest.cs deleted file mode 100644 index 795a614..0000000 --- a/src/Modules/TakeoutSaaS.Module.Storage/Models/StorageUploadRequest.cs +++ /dev/null @@ -1,61 +0,0 @@ -namespace TakeoutSaaS.Module.Storage.Models; - -/// -/// 对象存储上传请求参数。 -/// -/// -/// 初始化上传请求。 -/// -/// 对象键(含路径)。 -/// 文件流。 -/// 内容类型。 -/// 内容长度。 -/// 是否返回签名访问链接。 -/// 签名有效期。 -/// 附加元数据。 -public sealed class StorageUploadRequest( - string objectKey, - Stream content, - string contentType, - long contentLength, - bool generateSignedUrl, - TimeSpan signedUrlExpires, - IDictionary? metadata = null) -{ - /// - /// 对象键。 - /// - public string ObjectKey { get; } = objectKey; - - /// - /// 文件流。 - /// - public Stream Content { get; } = content; - - /// - /// 内容类型。 - /// - public string ContentType { get; } = contentType; - - /// - /// 内容长度。 - /// - public long ContentLength { get; } = contentLength; - - /// - /// 是否需要签名访问链接。 - /// - public bool GenerateSignedUrl { get; } = generateSignedUrl; - - /// - /// 签名有效期。 - /// - public TimeSpan SignedUrlExpires { get; } = signedUrlExpires; - - /// - /// 元数据集合。 - /// - public IReadOnlyDictionary Metadata { get; } = metadata == null - ? new Dictionary() - : new Dictionary(metadata); -} diff --git a/src/Modules/TakeoutSaaS.Module.Storage/Models/StorageUploadResult.cs b/src/Modules/TakeoutSaaS.Module.Storage/Models/StorageUploadResult.cs deleted file mode 100644 index c3af710..0000000 --- a/src/Modules/TakeoutSaaS.Module.Storage/Models/StorageUploadResult.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace TakeoutSaaS.Module.Storage.Models; - -/// -/// 上传结果信息。 -/// -public sealed class StorageUploadResult -{ - /// - /// 对象键。 - /// - public string ObjectKey { get; init; } = string.Empty; - - /// - /// 可访问的 URL(可能已包含签名)。 - /// - public string Url { get; init; } = string.Empty; - - /// - /// 带过期时间的签名 URL(若生成)。 - /// - public string? SignedUrl { get; init; } - - /// - /// 文件大小。 - /// - public long FileSize { get; init; } - - /// - /// 内容类型。 - /// - public string ContentType { get; init; } = string.Empty; -} diff --git a/src/Modules/TakeoutSaaS.Module.Storage/Options/AliyunOssOptions.cs b/src/Modules/TakeoutSaaS.Module.Storage/Options/AliyunOssOptions.cs deleted file mode 100644 index d17f548..0000000 --- a/src/Modules/TakeoutSaaS.Module.Storage/Options/AliyunOssOptions.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Module.Storage.Options; - -/// -/// 阿里云 OSS 访问配置。 -/// -public sealed class AliyunOssOptions -{ - /// - /// 访问密钥 ID。 - /// - [Required] - public string AccessKeyId { get; set; } = string.Empty; - - /// - /// 访问密钥 Secret。 - /// - [Required] - public string AccessKeySecret { get; set; } = string.Empty; - - /// - /// Endpoint,如 https://oss-cn-hangzhou.aliyuncs.com。 - /// - [Required] - [Url] - public string Endpoint { get; set; } = string.Empty; - - /// - /// 目标存储桶名称。 - /// - [Required] - public string Bucket { get; set; } = string.Empty; - - /// - /// CDN 加速域名(可选)。 - /// - [Url] - public string? CdnBaseUrl { get; set; } - - /// - /// 是否默认使用 HTTPS。 - /// - public bool UseHttps { get; set; } = true; -} diff --git a/src/Modules/TakeoutSaaS.Module.Storage/Options/QiniuKodoOptions.cs b/src/Modules/TakeoutSaaS.Module.Storage/Options/QiniuKodoOptions.cs deleted file mode 100644 index 7e6bf37..0000000 --- a/src/Modules/TakeoutSaaS.Module.Storage/Options/QiniuKodoOptions.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Module.Storage.Options; - -/// -/// 七牛云 Kodo S3 兼容网关配置。 -/// -public sealed class QiniuKodoOptions -{ - /// - /// AccessKey。 - /// - [Required] - public string AccessKey { get; set; } = string.Empty; - - /// - /// SecretKey。 - /// - [Required] - public string SecretKey { get; set; } = string.Empty; - - /// - /// 绑定的空间名称。 - /// - [Required] - public string Bucket { get; set; } = string.Empty; - - /// - /// 下载域名(CDN 域名或测试域名),用于生成访问链接。 - /// - [Url] - public string? DownloadDomain { get; set; } - - /// - /// S3 兼容网关 Endpoint(如 https://s3-cn-south-1.qiniucs.com),为空则使用官方默认。 - /// - [Url] - public string? Endpoint { get; set; } - - /// - /// 是否使用 HTTPS。 - /// - public bool UseHttps { get; set; } = true; - - /// - /// 直传或下载时默认有效期(分钟),未设置时使用全局安全配置。 - /// - [Range(1, 24 * 60)] - public int? SignedUrlExpirationMinutes { get; set; } -} diff --git a/src/Modules/TakeoutSaaS.Module.Storage/Options/StorageOptions.cs b/src/Modules/TakeoutSaaS.Module.Storage/Options/StorageOptions.cs deleted file mode 100644 index 465b1b7..0000000 --- a/src/Modules/TakeoutSaaS.Module.Storage/Options/StorageOptions.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Module.Storage.Options; - -/// -/// 存储模块的统一配置项,决定默认提供商与全局安全策略。 -/// -public sealed class StorageOptions -{ - /// - /// 默认使用的存储提供商。 - /// - public StorageProviderKind Provider { get; set; } = StorageProviderKind.TencentCos; - - /// - /// CDN 访问域名(可选),若配置则优先使用 CDN 域名生成访问地址。 - /// - [Url] - public string? CdnBaseUrl { get; set; } - - /// - /// 腾讯云 COS 配置。 - /// - [Required] - public TencentCosOptions TencentCos { get; set; } = new(); - - /// - /// 七牛云 Kodo 配置。 - /// - [Required] - public QiniuKodoOptions QiniuKodo { get; set; } = new(); - - /// - /// 阿里云 OSS 配置。 - /// - [Required] - public AliyunOssOptions AliyunOss { get; set; } = new(); - - /// - /// 存储安全策略配置。 - /// - [Required] - public StorageSecurityOptions Security { get; set; } = new(); -} diff --git a/src/Modules/TakeoutSaaS.Module.Storage/Options/StorageSecurityOptions.cs b/src/Modules/TakeoutSaaS.Module.Storage/Options/StorageSecurityOptions.cs deleted file mode 100644 index 0619faf..0000000 --- a/src/Modules/TakeoutSaaS.Module.Storage/Options/StorageSecurityOptions.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Module.Storage.Options; - -/// -/// 文件安全与防盗链相关配置。 -/// -public sealed class StorageSecurityOptions -{ - /// - /// 单个文件最大尺寸(字节),默认 10MB。 - /// - [Range(1, long.MaxValue)] - public long MaxFileSizeBytes { get; set; } = 10 * 1024 * 1024; - - /// - /// 允许的图片后缀名白名单。 - /// - [MinLength(1)] - public string[] AllowedImageExtensions { get; set; } = { ".jpg", ".jpeg", ".png", ".webp", ".gif" }; - - /// - /// 允许的通用文件后缀名白名单。 - /// - [MinLength(1)] - public string[] AllowedFileExtensions { get; set; } = { ".jpg", ".jpeg", ".png", ".webp", ".gif", ".pdf" }; - - /// - /// 默认签名有效期(分钟),用于生成带过期时间的访问链接。 - /// - [Range(1, 24 * 60)] - public int DefaultUrlExpirationMinutes { get; set; } = 30; - - /// - /// 是否启用来源校验(防盗链),为空则不校验。 - /// - public bool EnableRefererValidation { get; set; } = true; - - /// - /// 允许的 Referer/Origin 前缀列表,用于限制上传接口调用来源。 - /// - public string[] AllowedReferers { get; set; } = Array.Empty(); - - /// - /// 针对 CDN 防盗链的额外签名密钥(可选),用于生成二次校验签名。 - /// - public string? AntiLeechTokenSecret { get; set; } -} diff --git a/src/Modules/TakeoutSaaS.Module.Storage/Options/TencentCosOptions.cs b/src/Modules/TakeoutSaaS.Module.Storage/Options/TencentCosOptions.cs deleted file mode 100644 index 0808821..0000000 --- a/src/Modules/TakeoutSaaS.Module.Storage/Options/TencentCosOptions.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace TakeoutSaaS.Module.Storage.Options; - -/// -/// 腾讯云 COS 访问配置。 -/// -public sealed class TencentCosOptions -{ - /// - /// SecretId。 - /// - [Required] - public string SecretId { get; set; } = string.Empty; - - /// - /// SecretKey。 - /// - [Required] - public string SecretKey { get; set; } = string.Empty; - - /// - /// 存储地域(如 ap-guangzhou)。 - /// - [Required] - public string Region { get; set; } = string.Empty; - - /// - /// 存储桶名称(含 AppId,如 takeout-bucket-123456)。 - /// - [Required] - public string Bucket { get; set; } = string.Empty; - - /// - /// COS 自定义域名或 API Endpoint(可选),未配置则根据 Region 生成默认域名。 - /// - public string? Endpoint { get; set; } - - /// - /// CDN 域名(可选),用于生成加速访问地址。 - /// - [Url] - public string? CdnBaseUrl { get; set; } - - /// - /// 是否使用 HTTPS。 - /// - public bool UseHttps { get; set; } = true; - - /// - /// 是否强制使用 PathStyle 访问,COS 默认可使用虚拟主机形式。 - /// - public bool ForcePathStyle { get; set; } -} diff --git a/src/Modules/TakeoutSaaS.Module.Storage/Providers/AliyunOssStorageProvider.cs b/src/Modules/TakeoutSaaS.Module.Storage/Providers/AliyunOssStorageProvider.cs deleted file mode 100644 index 0244720..0000000 --- a/src/Modules/TakeoutSaaS.Module.Storage/Providers/AliyunOssStorageProvider.cs +++ /dev/null @@ -1,162 +0,0 @@ -using Aliyun.OSS; -using Microsoft.Extensions.Options; -using TakeoutSaaS.Module.Storage.Abstractions; -using TakeoutSaaS.Module.Storage.Models; -using TakeoutSaaS.Module.Storage.Options; - -namespace TakeoutSaaS.Module.Storage.Providers; - -/// -/// 阿里云 OSS 存储提供商实现。 -/// -public sealed class AliyunOssStorageProvider(IOptionsMonitor optionsMonitor) : IObjectStorageProvider, IDisposable -{ - private OssClient? _client; - private bool _disposed; - - private StorageOptions CurrentOptions => optionsMonitor.CurrentValue; - - /// - public StorageProviderKind Kind => StorageProviderKind.AliyunOss; - - /// - public async Task UploadAsync(StorageUploadRequest request, CancellationToken cancellationToken = default) - { - // 1. 准备元数据 - var options = CurrentOptions; - var metadata = new ObjectMetadata - { - ContentLength = request.ContentLength, - ContentType = request.ContentType - }; - - foreach (var kv in request.Metadata) - { - metadata.UserMetadata[kv.Key] = kv.Value; - } - - // Aliyun OSS SDK 支持异步方法,如未支持将同步封装为任务。 - // 2. 上传对象 - await PutObjectAsync(options.AliyunOss.Bucket, request.ObjectKey, request.Content, metadata, cancellationToken) - .ConfigureAwait(false); - - // 3. 生成签名或公有 URL - var signedUrl = request.GenerateSignedUrl - ? await GenerateDownloadUrlAsync(request.ObjectKey, request.SignedUrlExpires, cancellationToken).ConfigureAwait(false) - : null; - - // 4. 返回上传结果 - return new StorageUploadResult - { - ObjectKey = request.ObjectKey, - Url = signedUrl ?? BuildPublicUrl(request.ObjectKey), - SignedUrl = signedUrl, - FileSize = request.ContentLength, - ContentType = request.ContentType - }; - } - - /// - public Task CreateDirectUploadAsync(StorageDirectUploadRequest request, CancellationToken cancellationToken = default) - { - // 1. 计算过期时间并生成直传/下载链接 - var expiresAt = DateTimeOffset.UtcNow.Add(request.Expires); - var uploadUrl = GeneratePresignedUrl(request.ObjectKey, request.Expires, SignHttpMethod.Put, request.ContentType); - var downloadUrl = GeneratePresignedUrl(request.ObjectKey, request.Expires, SignHttpMethod.Get, null); - - // 2. 返回直传参数 - var result = new StorageDirectUploadResult - { - UploadUrl = uploadUrl, - FormFields = new Dictionary(), - ExpiresAt = expiresAt, - ObjectKey = request.ObjectKey, - SignedDownloadUrl = downloadUrl - }; - - return Task.FromResult(result); - } - - /// - public Task GenerateDownloadUrlAsync(string objectKey, TimeSpan expires, CancellationToken cancellationToken = default) - { - // 1. 生成预签名下载 URL - var url = GeneratePresignedUrl(objectKey, expires, SignHttpMethod.Get, null); - return Task.FromResult(url); - } - - /// - public string BuildPublicUrl(string objectKey) - { - var cdn = CurrentOptions.AliyunOss.CdnBaseUrl ?? CurrentOptions.CdnBaseUrl; - if (!string.IsNullOrWhiteSpace(cdn)) - { - return $"{cdn!.TrimEnd('/')}/{objectKey}"; - } - - var endpoint = CurrentOptions.AliyunOss.Endpoint.TrimEnd('/'); - var scheme = CurrentOptions.AliyunOss.UseHttps ? "https" : "http"; - // Endpoint 可能已包含协议,若没有则补充。 - if (!endpoint.StartsWith("http", StringComparison.OrdinalIgnoreCase)) - { - endpoint = $"{scheme}://{endpoint}"; - } - - return $"{endpoint}/{CurrentOptions.AliyunOss.Bucket}/{objectKey}"; - } - - /// - /// 上传对象到 OSS。 - /// - private async Task PutObjectAsync(string bucket, string key, Stream content, ObjectMetadata metadata, CancellationToken cancellationToken) - { - var client = EnsureClient(); - // SDK 无异步则封装为 Task - await Task.Run(() => client.PutObject(bucket, key, content, metadata), cancellationToken).ConfigureAwait(false); - } - - /// - /// 生成预签名 URL。 - /// - private string GeneratePresignedUrl(string objectKey, TimeSpan expires, SignHttpMethod method, string? contentType) - { - var request = new GeneratePresignedUriRequest(CurrentOptions.AliyunOss.Bucket, objectKey, method) - { - Expiration = DateTime.Now.Add(expires) - }; - - if (!string.IsNullOrWhiteSpace(contentType)) - { - request.ContentType = contentType; - } - - var uri = EnsureClient().GeneratePresignedUri(request); - return uri.ToString(); - } - - /// - /// 构建或复用 OSS 客户端。 - /// - private OssClient EnsureClient() - { - if (_client != null) - { - return _client; - } - - var options = CurrentOptions.AliyunOss; - _client = new OssClient(options.Endpoint, options.AccessKeyId, options.AccessKeySecret); - return _client; - } - - /// - public void Dispose() - { - if (_disposed) - { - return; - } - - _disposed = true; - } -} diff --git a/src/Modules/TakeoutSaaS.Module.Storage/Providers/QiniuKodoStorageProvider.cs b/src/Modules/TakeoutSaaS.Module.Storage/Providers/QiniuKodoStorageProvider.cs deleted file mode 100644 index bccb657..0000000 --- a/src/Modules/TakeoutSaaS.Module.Storage/Providers/QiniuKodoStorageProvider.cs +++ /dev/null @@ -1,52 +0,0 @@ -using Microsoft.Extensions.Options; -using TakeoutSaaS.Module.Storage.Options; - -namespace TakeoutSaaS.Module.Storage.Providers; - -/// -/// 七牛云 Kodo(S3 兼容网关)存储提供商。 -/// -public sealed class QiniuKodoStorageProvider(IOptionsMonitor optionsMonitor) - : S3StorageProviderBase -{ - private StorageOptions CurrentOptions => optionsMonitor.CurrentValue; - - /// - public override StorageProviderKind Kind => StorageProviderKind.QiniuKodo; - - /// - protected override string Bucket => CurrentOptions.QiniuKodo.Bucket; - - /// - protected override string ServiceUrl => string.IsNullOrWhiteSpace(CurrentOptions.QiniuKodo.Endpoint) - ? $"{(CurrentOptions.QiniuKodo.UseHttps ? "https" : "http")}://s3.qiniucs.com" - : CurrentOptions.QiniuKodo.Endpoint!; - - /// - protected override string AccessKey => CurrentOptions.QiniuKodo.AccessKey; - - /// - protected override string SecretKey => CurrentOptions.QiniuKodo.SecretKey; - - /// - protected override bool UseHttps => CurrentOptions.QiniuKodo.UseHttps; - - /// - protected override bool ForcePathStyle => true; - - /// - protected override string? CdnBaseUrl => !string.IsNullOrWhiteSpace(CurrentOptions.QiniuKodo.DownloadDomain) - ? CurrentOptions.QiniuKodo.DownloadDomain - : CurrentOptions.CdnBaseUrl; - - /// - protected override TimeSpan SignedUrlExpiry - { - get - { - var minutes = CurrentOptions.QiniuKodo.SignedUrlExpirationMinutes - ?? CurrentOptions.Security.DefaultUrlExpirationMinutes; - return TimeSpan.FromMinutes(Math.Max(1, minutes)); - } - } -} diff --git a/src/Modules/TakeoutSaaS.Module.Storage/Providers/S3StorageProviderBase.cs b/src/Modules/TakeoutSaaS.Module.Storage/Providers/S3StorageProviderBase.cs deleted file mode 100644 index 6251c01..0000000 --- a/src/Modules/TakeoutSaaS.Module.Storage/Providers/S3StorageProviderBase.cs +++ /dev/null @@ -1,243 +0,0 @@ -using Amazon.Runtime; -using Amazon.S3; -using Amazon.S3.Model; -using TakeoutSaaS.Module.Storage.Abstractions; -using TakeoutSaaS.Module.Storage.Models; - -namespace TakeoutSaaS.Module.Storage.Providers; - -/// -/// 基于 AWS S3 SDK 的通用存储提供商基类,可复用到 COS 与 Kodo 等兼容实现。 -/// -public abstract class S3StorageProviderBase : IObjectStorageProvider, IDisposable -{ - private IAmazonS3? _client; - private bool _disposed; - - /// - public abstract StorageProviderKind Kind { get; } - - /// - /// 目标桶名称。 - /// - protected abstract string Bucket { get; } - - /// - /// S3 服务端点,需包含协议。 - /// - protected abstract string ServiceUrl { get; } - - /// - /// 访问凭证 ID。 - /// - protected abstract string AccessKey { get; } - - /// - /// 访问凭证密钥。 - /// - protected abstract string SecretKey { get; } - - /// - /// 是否使用 HTTPS。 - /// - protected abstract bool UseHttps { get; } - - /// - /// 是否强制 PathStyle 访问。 - /// - protected abstract bool ForcePathStyle { get; } - - /// - /// CDN 域名(可选)。 - /// - protected abstract string? CdnBaseUrl { get; } - - /// - /// 默认签名有效期。 - /// - protected abstract TimeSpan SignedUrlExpiry { get; } - - /// - public virtual async Task UploadAsync(StorageUploadRequest request, CancellationToken cancellationToken = default) - { - // 0. 兜底重置流位置,避免上游读取导致内容缺失 - if (request.Content.CanSeek) - { - request.Content.Position = 0; - } - - // 1. 构建上传请求 - var putRequest = new PutObjectRequest - { - BucketName = Bucket, - Key = request.ObjectKey, - InputStream = request.Content, - AutoCloseStream = false, - ContentType = request.ContentType, - DisableDefaultChecksumValidation = true, - UseChunkEncoding = false, - DisablePayloadSigning = true - }; - - // 1.1 显式设置 Content-Length,避免 S3 SDK 对兼容网关使用 aws-chunked 导致对象内容被写入“chunk-signature”头而损坏 - if (request.ContentLength > 0) - { - putRequest.Headers.ContentLength = request.ContentLength; - } - - foreach (var kv in request.Metadata) - { - putRequest.Metadata[kv.Key] = kv.Value; - } - - // 2. 执行上传 - await Client.PutObjectAsync(putRequest, cancellationToken).ConfigureAwait(false); - - // 3. 根据需要生成签名 URL - var signedUrl = request.GenerateSignedUrl - ? GenerateSignedUrl(request.ObjectKey, request.SignedUrlExpires) - : null; - - // 4. 返回上传结果 - return new StorageUploadResult - { - ObjectKey = request.ObjectKey, - Url = signedUrl ?? BuildPublicUrl(request.ObjectKey), - SignedUrl = signedUrl, - FileSize = request.ContentLength, - ContentType = request.ContentType - }; - } - - /// - public virtual Task CreateDirectUploadAsync(StorageDirectUploadRequest request, CancellationToken cancellationToken = default) - { - // 1. 计算过期时间并生成直传 URL - var expiresAt = DateTimeOffset.UtcNow.Add(request.Expires); - var uploadUrl = GenerateSignedUrl(request.ObjectKey, request.Expires, HttpVerb.PUT, request.ContentType); - var signedDownload = GenerateSignedUrl(request.ObjectKey, request.Expires); - - // 2. 返回直传参数 - var result = new StorageDirectUploadResult - { - UploadUrl = uploadUrl, - FormFields = new Dictionary(), - ExpiresAt = expiresAt, - ObjectKey = request.ObjectKey, - SignedDownloadUrl = signedDownload - }; - - return Task.FromResult(result); - } - - /// - public virtual Task GenerateDownloadUrlAsync(string objectKey, TimeSpan expires, CancellationToken cancellationToken = default) - { - // 1. 生成下载签名 URL - var url = GenerateSignedUrl(objectKey, expires); - return Task.FromResult(url); - } - - /// - public virtual string BuildPublicUrl(string objectKey) - { - if (!string.IsNullOrWhiteSpace(CdnBaseUrl)) - { - return $"{CdnBaseUrl!.TrimEnd('/')}/{objectKey}"; - } - - var endpoint = new Uri(ServiceUrl); - var scheme = UseHttps ? "https" : "http"; - return $"{scheme}://{Bucket}.{endpoint.Host}/{objectKey}"; - } - - /// - /// 生成预签名 URL。 - /// - /// 对象键。 - /// 过期时间。 - /// HTTP 动作。 - /// 可选的内容类型约束。 - protected virtual string GenerateSignedUrl(string objectKey, TimeSpan expires, HttpVerb verb = HttpVerb.GET, string? contentType = null) - { - var request = new GetPreSignedUrlRequest - { - BucketName = Bucket, - Key = objectKey, - Verb = verb, - Expires = DateTime.UtcNow.Add(expires), - Protocol = UseHttps ? Protocol.HTTPS : Protocol.HTTP - }; - - if (!string.IsNullOrWhiteSpace(contentType)) - { - request.Headers["Content-Type"] = contentType; - } - - return Client.GetPreSignedURL(request); - } - - /// - /// 创建 S3 客户端。 - /// - protected virtual IAmazonS3 CreateClient() - { - // 1. 尽量推断鉴权 Region(腾讯云 COS 的 S3 兼容域名形如:cos.ap-beijing.myqcloud.com) - var authenticationRegion = ResolveAuthenticationRegion(ServiceUrl); - - // 2. 构建客户端配置 - var config = new AmazonS3Config - { - ServiceURL = ServiceUrl, - ForcePathStyle = ForcePathStyle, - UseHttp = !UseHttps, - AuthenticationRegion = authenticationRegion - }; - - // 3. 创建客户端并返回 - var credentials = new BasicAWSCredentials(AccessKey, SecretKey); - return new AmazonS3Client(credentials, config); - } - - private static string? ResolveAuthenticationRegion(string serviceUrl) - { - // 1. 解析 URL - if (!Uri.TryCreate(serviceUrl, UriKind.Absolute, out var uri)) - { - return null; - } - - // 2. 提取 Host - var host = uri.Host; - if (string.IsNullOrWhiteSpace(host)) - { - return null; - } - - // 3. 按 COS 域名规则解析 Region - const string cosPrefix = "cos."; - const string cosSuffix = ".myqcloud.com"; - if (host.StartsWith(cosPrefix, StringComparison.OrdinalIgnoreCase) && - host.EndsWith(cosSuffix, StringComparison.OrdinalIgnoreCase)) - { - var regionPart = host.Substring(cosPrefix.Length, host.Length - cosPrefix.Length - cosSuffix.Length); - return string.IsNullOrWhiteSpace(regionPart) ? null : regionPart; - } - return null; - } - - private IAmazonS3 Client => _client ??= CreateClient(); - - /// - public void Dispose() - { - if (_disposed) - { - return; - } - - _disposed = true; - _client?.Dispose(); - GC.SuppressFinalize(this); - } -} diff --git a/src/Modules/TakeoutSaaS.Module.Storage/Providers/TencentCosStorageProvider.cs b/src/Modules/TakeoutSaaS.Module.Storage/Providers/TencentCosStorageProvider.cs deleted file mode 100644 index 259d6e4..0000000 --- a/src/Modules/TakeoutSaaS.Module.Storage/Providers/TencentCosStorageProvider.cs +++ /dev/null @@ -1,45 +0,0 @@ -using Microsoft.Extensions.Options; -using TakeoutSaaS.Module.Storage.Options; - -namespace TakeoutSaaS.Module.Storage.Providers; - -/// -/// 腾讯云 COS 存储提供商实现。 -/// -public sealed class TencentCosStorageProvider(IOptionsMonitor optionsMonitor) - : S3StorageProviderBase -{ - private StorageOptions CurrentOptions => optionsMonitor.CurrentValue; - - /// - public override StorageProviderKind Kind => StorageProviderKind.TencentCos; - - /// - protected override string Bucket => CurrentOptions.TencentCos.Bucket; - - /// - protected override string ServiceUrl => string.IsNullOrWhiteSpace(CurrentOptions.TencentCos.Endpoint) - ? $"{(CurrentOptions.TencentCos.UseHttps ? "https" : "http")}://cos.{CurrentOptions.TencentCos.Region}.myqcloud.com" - : CurrentOptions.TencentCos.Endpoint!; - - /// - protected override string AccessKey => CurrentOptions.TencentCos.SecretId; - - /// - protected override string SecretKey => CurrentOptions.TencentCos.SecretKey; - - /// - protected override bool UseHttps => CurrentOptions.TencentCos.UseHttps; - - /// - protected override bool ForcePathStyle => CurrentOptions.TencentCos.ForcePathStyle; - - /// - protected override string? CdnBaseUrl => !string.IsNullOrWhiteSpace(CurrentOptions.TencentCos.CdnBaseUrl) - ? CurrentOptions.TencentCos.CdnBaseUrl - : CurrentOptions.CdnBaseUrl; - - /// - protected override TimeSpan SignedUrlExpiry => - TimeSpan.FromMinutes(Math.Max(1, CurrentOptions.Security.DefaultUrlExpirationMinutes)); -} diff --git a/src/Modules/TakeoutSaaS.Module.Storage/Services/StorageProviderResolver.cs b/src/Modules/TakeoutSaaS.Module.Storage/Services/StorageProviderResolver.cs deleted file mode 100644 index b1920c0..0000000 --- a/src/Modules/TakeoutSaaS.Module.Storage/Services/StorageProviderResolver.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Microsoft.Extensions.Options; -using TakeoutSaaS.Module.Storage.Abstractions; -using TakeoutSaaS.Module.Storage.Options; - -namespace TakeoutSaaS.Module.Storage.Services; - -/// -/// 存储提供商解析器,实现基于配置的提供商选择。 -/// -public sealed class StorageProviderResolver(IOptionsMonitor optionsMonitor, IEnumerable providers) - : IStorageProviderResolver -{ - private readonly IDictionary _providerMap = - providers.ToDictionary(x => x.Kind, x => x); - - /// - public IObjectStorageProvider Resolve(StorageProviderKind? provider = null) - { - var target = provider ?? optionsMonitor.CurrentValue.Provider; - if (_providerMap.TryGetValue(target, out var instance)) - { - return instance; - } - - throw new InvalidOperationException($"未注册存储提供商:{target}"); - } -} diff --git a/src/Modules/TakeoutSaaS.Module.Storage/StorageProviderKind.cs b/src/Modules/TakeoutSaaS.Module.Storage/StorageProviderKind.cs deleted file mode 100644 index 589b9f8..0000000 --- a/src/Modules/TakeoutSaaS.Module.Storage/StorageProviderKind.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace TakeoutSaaS.Module.Storage; - -/// -/// 存储提供商类型枚举,便于通过配置选择具体的对象存储实现。 -/// -public enum StorageProviderKind -{ - /// - /// 腾讯云 COS 对象存储。 - /// - TencentCos = 1, - - /// - /// 七牛云 Kodo 存储。 - /// - QiniuKodo = 2, - - /// - /// 阿里云 OSS 存储。 - /// - AliyunOss = 3 -}