diff --git a/.gitignore b/.gitignore index 1cfc635..afacaef 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -docs/AML_Backend/docker-compose-local-dev/AML-local-dev.bak \ No newline at end of file +docs/AML_Backend/docker-compose-local-dev/AML-local-dev.bak diff --git a/docs/AML_Backend/数据库迁移指南/readme.md b/docs/AML_Backend/数据库迁移指南/readme.md new file mode 100644 index 0000000..5fe5558 --- /dev/null +++ b/docs/AML_Backend/数据库迁移指南/readme.md @@ -0,0 +1,21 @@ +# 数据库迁移指南 + +## 前置条件 +- vs开发环境 +- 确保项目已经成功构建 +- 确保已安装Entity Framework Core工具 + +## 迁移步骤 +1. 在Visual Studio中将`EntityFrameworkCore.DbMigrations`设置为启动项目 +2. 打开包管理器控制台(Package Manager Console) +3. 将默认项目设置为:`src\EntityFrameworkCore.DbMigrations` +4. 执行迁移命令: + ``` + Add-Migration + ``` +5. 迁移将自动应用到数据库 + +## 注意事项 +- 每次修改实体模型后都需要创建新的迁移 +- 可以使用`Remove-Migration`命令撤销上一次迁移 +- 确保数据库连接字符串配置正确 diff --git a/docs/justsolutionsWebV2/plan-plus-api实现报告202607062356.html b/docs/justsolutionsWebV2/plan-plus-api实现报告202607062356.html new file mode 100644 index 0000000..ce767ec --- /dev/null +++ b/docs/justsolutionsWebV2/plan-plus-api实现报告202607062356.html @@ -0,0 +1,304 @@ + + + + + +justsolutionsWebV2 · plans-plus 真實 API 對接實現報告 + + + + +
+ +
+

justsolutionsWebV2 · plans-plus 真實 API 對接實現報告

+

plan-plus-api分析.html 的方案,把 public/plans-plus.html 單頁訂閱流程從 mock 切換到 AML 後端(iCON.Abp.AMLPortal)真實 API,並在本地 docker-compose-local-dev 環境跑通、逐流程實測(支付除外)。本文記錄實際落地內容與驗證結果。

+

範圍:AML_Backend(後端 3 項改動 + 配置)· justsolutionsWebV2/server(BFF 真實路由)· docker-compose-local-dev(本地棧 + 數據恢復)

+

狀態(2026-07-06 實測):P1 只讀目錄 / P2 新購 / P3 續費·加購 / P4 聯絡我們 —— 全部端到端打通並真實入庫;支付與單次查詢真實檢測編排本輪除外(保持 mock)。

+
+ + + + +
+

1. 落地結論速覽

+

plans-plus 依賴的 3 條只讀目錄(editions / plans/catalog / countries)、2 條交互查詢(agents / tenants/lookup)、下單提交(subscribe,含 new/renew/topup)與 聯絡我們(subscribe-offline → CreateFeedback)均已對接真實後端並實測通過。單次查詢與支付本輪除外,仍走 mock 兜底。

+ + + + + + + + + + + + + +
前端端點對應後端狀態實測結果
GET /editionsOrder/portal/GetEditionList完成9 行業(過濾 Standard/DC、Others 置末);jQSeparatedEditions 對齊真實 CPA GUID
GET /plans/catalogplan/portal/GetPlanList完成HKG·HKD 目錄;standard/cpa/addons 全帶 planDetailId;KYC 月租 + jQuota 配套
GET /countriesOrder/getCategoryByTypes完成249 國;已改免 token(原用 OAuth,本地無憑證會失敗)
GET /agents/:codeSearchUserByCodeAndType + GetPlanList(agentUserId)完成返回 {code,name,tiers,email,phone,agentorId};tiers 經二次 GetPlanList 推導,空=不過濾
GET /tenants/lookup新增 Order/portal/queryRenewableTenantByEmail完成後端新端點按郵箱聚合 currentSubscription+referrer;cpa1 唯一命中
POST /subscribe newOrder/portal/CreateOrder完成空 BR / 個人主體 / 加值項 / agent 均建單入庫(BR/CI 已放開)
POST /subscribe renew·topupOrder/portal/TenantRenewal完成cpa1 續費 / jQuota 加購均建單;修復內部 token URL 後通過
POST /subscribe-offline
(聯絡我們/推薦人)
customer/CreateFeedback完成訂單摘要序列化為 message;有推薦人則寫 AssignedAgentUserId 路由收件人
/single-query · /payments/*ConsumerPortal(待後端)· 支付方(未定)本輪除外保持 mock 兜底;文檔明確除外
+
+ + +
+

2. 數據恢復(.bak → AbpAML)

+

docs/AML_Backend/docker-compose-local-dev/AML-local-dev.bak(201MB,SQL Server 備份,內部庫名 AML-local-dev)恢復真實開發數據,取代原「補種子 SQL」路線——恢復後目錄 / 租戶 / 代理計劃齊備,直接可對接。

+
docker stop aml-httpapi-host → ALTER DATABASE AbpAML SET SINGLE_USER WITH ROLLBACK IMMEDIATE → RESTORE DATABASE AbpAML FROM DISK WITH MOVE(AML-local-dev→AbpAML.mdf, AML-local-dev_log→AbpAML_log.ldf), REPLACE → docker start aml-httpapi-host
+

恢復為 AbpAML(host 連接的庫),MOVE 邏輯文件到 /var/opt/mssql/data/AbpAML.mdf/_log.ldf;恢復前停 host 釋放連接、置 SINGLE_USER 取得獨佔。

+ + + + + + + + + +
恢復後用途
AMLPortal_Plans / PlanDetails123 / 123方案目錄(按國家分兩套:HKG-HKD 與 JPN-USD,靠 systemCode/countryCode 區分)
SaasEditions12(含真實 CPA 3A1A296B-…所屬行業
SaasTenants / AMLPortal_TenantPropertys42 / 98續費 / 加購測試數據
AMLPortal_AgentUserPlans24agent tiers 過濾
AMLPortal_Orders / AbpUsers142 / 131訂單反查 / 推薦人
+

catalog 國家過濾:services/catalog.js 默認過濾 HKG(香港市場·HKD,與舊 mock 幣種一致);/plans-jp 的 PAYG 定價另走 JPN

+
+ + +
+

3. 後端改動(AML_Backend)

+

共 3 項代碼改動 + 2 項配置,全部重建 httpapi-host 鏡像後實測通過。

+ +

3.1 BR/CI 非必填 完成

+

注釋 OrderService.cs CreateOrder 的兩處 BR/CI 必填校驗(前置校驗處 + Organization BR/CI required 處),保留唯一性校驗 ExistsByOrganizationBRCI(對 BR、CI 皆空返回 false,空值安全)。個人主體 / 空 BR 可下單。

+ +

3.2 新增 queryRenewableTenantByEmail 端點 新增

+
POST /api/amlPortal/Order/portal/queryRenewableTenantByEmail AbpAutoAuth("Portal")
+

解決舊 queryRenewableTenant 只能按租戶名 DB 搜、無法按郵箱過濾的維度錯位。新端點維度反轉

+
    +
  • UserName=='admin' && Email==email 定位租戶管理員(禁多租戶過濾,全庫掃描可接受);
  • +
  • 取該租戶 IsActiveTenantProperty(含 Order→OrderDetails→Plan),按 CreationTime 取最新;
  • +
  • 反查訂單明細聚合 currentSubscription:基礎方案(B)→planId/名稱/月數/價;AdlU→addons.users(PCS 之和);jQ/j→jquotaPackageIdEnableKYC→kyc;並解析 EditionName(由 EditionId)與 referrer(由 AgentorId 解析用戶)。
  • +
+

新增 DTO:QueryRenewableTenantByEmailParamRenewableTenantByEmailDto(含 CurrentSubscriptionDto / RenewableReferrerDto)。

+ +

3.3 CreateFeedbackAssignedAgentUserId(聯絡推薦人路由)完成

+

Feedback 實體 + CreateFeedbackDto 加可空 AssignedAgentUserId(AutoMapper 同名自動映射);CustomerService.CreateFeedback 於有值時用 GetUsersByIDs 解析推薦人郵箱,作 SendEmailOnPortalFeedback 的收件人(無郵箱回退平台銷售),給客戶本人的確認郵件不變。

+

EF 遷移(部署待辦):本地以 ALTER TABLE AMLPortal_Feedbacks ADD AssignedAgentUserId uniqueidentifier NULL 加列(實體屬性映射到該列即可運行)。正式部署需在構建環境跑 dotnet ef migrations add 生成遷移(就一句 AddColumn)——原因:運行時 Database.Migrate() 會讀取遷移的 TargetModel(完整模型快照),手寫遷移不可行。

+ +

3.4 對齊 jQSeparatedEditions CPA GUID 完成

+

appsettings.local.jsonPortal.jQSeparatedEditions.EditionIds 由庫中不存在的 3A1A2969-… 改為真實 CPA edition 3A1A296B-DAB4-4B94-B267-4424683B8916,否則前端選 CPA 不觸發 isCpa 方案集切換。

+ +

3.5 修正內部 token URL(本地)完成

+

實測中發現的坑:AppConfig:General:ApiLocalhostUrl 出廠 https://localhost:44331/,但本地 host 只監聽 HTTP → TenantRenewal / 建租戶等內部 AbpTokenService.connect/token 調用 SSL 握手失敗(500)docker-compose.local.yml host env 已加 AppConfig__General__ApiLocalhostUrl: "http://localhost:44331/"。(CreateOrder 走異步隊列建租戶未同步觸發,故只有 renew/topup 報錯——由此定位。)

+
+ + +
+

4. BFF 對接(justsolutionsWebV2)

+

採 BFF 範式:瀏覽器只調本站 /api/*,服務端匿名代理後端並裁剪響應。前端 plans-plus.js 零改動

+

免 token:門戶端點均 [AbpAutoAuth("Portal")]SearchUserByCodeAndType[AllowAnonymous])——後端 AbpAutoAuthMiddleware 服務端注入門戶訪客 token 並覆蓋 Authorization,故 BFF 匿名 POST/GET 即可,無需配 AUTH_*。統一助手 server/services/portal.js

+ + + + + + + + + + + + + + +
文件職責
services/portal.js 匿名 POST/GET 助手(axios + 自簽證書放行 + {code,msg,data} 拆包)
services/catalog.js GetPlanList → 按國家(默認 HKG)過濾 → filterPlan 拆 standard/cpa/addons → 產出前端契約 + planDetailId 索引;5 分鐘緩存
routes/editions.js GetEditionList → 多語言映射 + 過濾 Standard/DC + Others 置末 + jQSeparatedEditions 鍵名/值轉小寫
routes/plans.js GET /plans/catalog[?countryCode] → catalog 服務
routes/agents.js GET /agents/:code → SearchUser + GetPlanList(agentUserId) 推導 tiers
routes/tenants.js GET /tenants/lookup?email= → queryRenewableTenantByEmail,字段直通 + 命中態 + 日期格式化
routes/subscribe.js POST /subscribe(new→CreateOrder / renew·topup→TenantRenewal,組裝 PlanList 回填 planDetailId、KYC PCS=月數) + POST /subscribe-offline(序列化摘要 + agentCode 解析→AssignedAgentUserId → CreateFeedback)
routes/countries.js 由 OAuth 改免 token(本地無憑證),輸出不變
index.js 真實路由挂在 mock 之前:真實路由處理訂閱流程,mock 只兜底 single-query/options、PAYG-GetPlanList、payments、promos
package.json 補回 start:local 腳本
+

PlanList 組裝(subscribe 核心)

+
PlanList = []
+if type != 'topup': push({PlanId: plan.planId, PlanDetailId: plan.planDetailId, PCS:1})
+if addons.users > 0:  push({PlanId: refs.user.planId,  PlanDetailId: refs.user.planDetailId,  PCS: users})
+if addons.kyc:        push({PlanId: refs.kyc.planId,   PlanDetailId: refs.kyc.planDetailId,   PCS: kycRentalMonths})  // KYC 月租
+if addons.jquotaPackageId: push({PlanId: jqId, PlanDetailId: planDetailByPlanId[jqId], PCS:1})
+
+ + +
+

5. 本地運行與驗證方式

+

① 後端棧(docker-compose-local-dev)

+
cd AML_Backend/docker-compose-local-dev
+docker compose -f docker-compose.local.yml build httpapi-host        # 編譯後端改動
+docker compose -f docker-compose.local.yml up -d --no-deps httpapi-host   # 只重建 host,不重跑 migrator
+# 後端 Swagger: http://localhost:44331/swagger   DB: localhost,11433 (sa / Aml@Local2026)
+

② BFF(justsolutionsWebV2)

+
cd justsolutionsWebV2
+npm run start:local
+# = APP_ENV=dev API_BASE_URL=http://localhost:44331 PLANS_PLUS_MOCK=true PORT=8090
+# 頁面: http://localhost:8090/plans-plus  (日本版 /plans-jp)
+

PLANS_PLUS_MOCK=true 讓 single-query/payments 走 mock 兜底;真實訂閱路由挂在 mock 之前優先處理。

+
+ + +
+

6. 端到端測試結果

+

以下均為 APP_ENV=dev、指向本地 docker 後端 的真實調用(非 mock),並核對數據庫寫入。

+ + + + + + + + + + +
流程驗證
只讀目錄editions=9 行業(CPA 用對齊 GUID)· catalog standard/cpa/addons 全帶 planDetailId · countries=249 · agents/C99099 返回 tiers/email/agentorId
租戶查詢tenants/lookup?email=307736951@qq.com → cpa1 唯一命中,聚合 editionId=CPA / referrer / currentSubscription(kyc=true, expiry 2027)
新購(多變體)4 筆真實訂單入庫:基礎 / 個人主體+空 BR / 全加值項(Standard+jQuota+增加使用人+KYC) / agent;GoodsName 顯示 PlanList 組裝正確
續費 / 加購cpa1 續費(CPA 24 Months) + jQuota 200 加購 均建單入庫(修 token URL 後)
聯絡我們/推薦人subscribe-offline → Feedback 寫入,AssignedAgentUserId=3A09C9F3…(推薦人)、摘要序列化 245 字
前端渲染(無頭 Chrome)行業下拉填充真實 editions、jQuota 真實 HKD 價渲染、無 JS 錯誤
+

結論:P1–P4 全部端到端打通,真實建單入庫,前端真實渲染。

+
+ + +
+

7. 本輪除外與後續待辦

+
    +
  • 除外 在線支付:文檔明確本輪除外;前端 submit 已臨時去支付鏈、直接顯示「已提交成功」。
  • +
  • 除外 單次查詢真實檢測編排:支付完成後 AML 後端內部 CreateConsumerLinkCreateConsumerOrder(待後端 + 需 2C 租戶/檢測引擎),本輪保持 mock。
  • +
  • 部署待辦 AssignedAgentUserId 正式 EF 遷移:本地已 ALTER 加列;部署環境需 dotnet ef migrations add 生成遷移(trivial AddColumn)。
  • +
  • 數據 邊界情況:測試數據中 test@test.com 對應 3 個租戶(郵箱非全局唯一,生產唯一);部分租戶 active TenantProperty 無關聯 Order → currentSubscription.planId 為空(前端 renewalPlanObj 兜底)。
  • +
  • 展示 後端無字段bestValue / note* / nameJP / edition 多語言由 BFF 靜態映射補足(日文暫回退英文)。
  • +
+
+ + +
+

8. 變更文件清單

+

AML_Backend

+
    +
  • modules/iCON.Abp.AMLPortal/…/OrderService.cs — BR/CI 放開 + QueryRenewableTenantByEmail
  • +
  • …/Application.Contracts/OrderAppLayer/{IOrderService,QueryRenewableTenantByEmailParam,RenewableTenantByEmailDto}.cs
  • +
  • …/HttpApi/Controllers/OrderController.cs — 新端點路由
  • +
  • …/Domain/DbEntity/Feedback.cs · …/Application.Contracts/CustomerAppLayer/CreateFeedbackDto.cs · …/Application/CustomerService.csAssignedAgentUserId
  • +
  • docker-compose-local-dev/appsettings.local.json — jQSeparatedEditions GUID
  • +
  • docker-compose-local-dev/docker-compose.local.ymlApiLocalhostUrl http override
  • +
+

justsolutionsWebV2

+
    +
  • 新增 server/services/{portal,catalog}.jsserver/routes/{editions,plans,agents,tenants,subscribe}.js
  • +
  • 修改 server/routes/countries.js(免 token)、server/index.js(挂載)、package.jsonstart:local
  • +
+
+

本報告基於 2026-07-06 本地 docker 環境實測。配套方案文檔見 plan-plus-api分析.html

+
+ +
+ + +