Major v3 changes: - Q12-Q18: MaxWeeklyBalancesPerLeg, MaxNetworkLevel, MagicWalletMaxDeposit, MagicWalletMaxCredit all become per-package (not global SystemConstants) - NetworkWeeklyBalance gets PackageId + Unique(UserId,WeekId,PackageId) - SP changes: @MaxBalancesPerLeg and @MaxNetworkLevel as dynamic params (removing hardcoded 300/15) - SpCommissionCalculationStrategy: pass package settings to SPs - Carryover per-package: week-shifting only for same PackageId records - commission.proto: package_id+package_title in 4 message types, new CustomerCommissionPackageSummary message, package filter in requests - FrontOffice: commission dashboard with per-package summary cards - BackOffice: package filter dropdown in all commission reports + CSV - Package Create/Edit: Quick Access checkboxes for features inline - Seed data: silver MaxBalancesPerLeg=30, MagicWalletMax=100M/250M - Migration: NetworkWeeklyBalances existing records get base PackageId - Impact Analysis: 39 -> 48+ changes across 6 layers - Timeline: 14 -> 17 days critical path (+3 days for per-package work) Updated docs: - business/BIZ-PACKAGE-BASED-SYSTEM.md (v2 -> v3) - roadmap/PACKAGE-TRANSFORMATION-TASKS.md (synced with v3)
22 KiB
🔄 نقشهراه تحول پکیجبیس — تسکهای گامبهگام
وضعیت: تاییدشده — آماده شروع
تاریخ: ۱۴۰۴/۱۲/۰۶
پیشنیاز: BIZ-PACKAGE-BASED-SYSTEM.md v3 (تکمیل پورسانت per-package)
هدف: شکستن ۴۸+ تغییر به تسکهای اتمیک با ترتیب اجرا و وابستگیها
⚠️ تغییرات v3: پورسانت per-package، carryover مجزا، SP parameters داینامیک، گزارشدهی FO/BO per-package
📊 نمای کلی
مرحله ۰: فیکس باگ فوری (۱ روز)
└─→ مرحله ۱: زیرساخت Domain + DB (۴ روز) ← +۱ روز (v3: NetworkWeeklyBalance)
├─→ مرحله ۲: منطق کسبوکار (۴ روز) ← موازی
│ └─→ مرحله ۴: UI (۵ روز) ← +۲ (v3: FO/BO گزارش per-package)
└─→ مرحله ۳: پورسانت (۴ روز) ← +۱ (v3: SP params + carryover)
└─→ مرحله ۵: تست + استقرار (۳ روز) ← +۱
مسیر بحرانی: ۰→۱→۲→۴→۵ = ~۱۷ روز (v2: ۱۳ روز)
مرحله ۰ — فیکس باگهای فوری
⏱️ ۱ روز | وابستگی: ندارد | ریسک: کم
✅ وضعیت باگها (بررسی اولیه لازم)
| # | باگ | Handler | شرح فیکس |
|---|---|---|---|
| B1 | DiscountBalance شارژ نمیشود | VerifyGoldenPackagePurchaseCommandHandler |
اضافه DiscountBalance += Amount × 2 + WalletChangeLog |
| B2 | UserPackagePurchase ساخته نمیشود | VerifyGoldenPackagePurchaseCommandHandler |
ساخت record بعد verify موفق |
| B3 | UserPackagePurchase ساخته نمیشود | VerifyPackagePurchaseCommandHandler |
ساخت record بعد verify موفق |
| B4 | UserPackagePurchase ساخته نمیشود | VerifyBasePackagePaymentCommandHandler |
ساخت record بعد verify موفق |
دستور کار B1:
1. باز کردن VerifyGoldenPackagePurchaseCommandHandler.cs
2. پیدا کردن جایی که Balance شارژ میشود
3. اضافه کردن:
wallet.DiscountBalance += command.Amount * 2;
// + ساخت WalletChangeLog برای DiscountBalance
4. تست: verify → چک DiscountBalance در DB
دستور کار B2-B4 (الگوی مشترک):
1. بعد از verify موفق و شارژ wallet:
var purchase = new UserPackagePurchase
{
UserId = userId,
PackageId = packageId, // فعلاً BasePackageId = 4
PurchaseDate = DateTime.UtcNow,
Amount = amount,
PurchaseMethod = purchaseMethod, // ZarinPal, BFF, etc.
TransactionId = transactionId,
IsVerified = true
};
_context.UserPackagePurchases.Add(purchase);
2. تست: verify → چک UserPackagePurchases table
مرحله ۱ — زیرساخت (Domain + DB)
⏱️ ۳ روز | وابستگی: مرحله ۰ | ریسک: متوسط (migration)
T1.1 — بروزرسانی Package Entity (۱۱ فیلد جدید — v3)
فایل: CMS/src/CMSMicroservice.Domain/Entities/Package.cs
+ public int SortOrder { get; set; }
+ public bool IsActive { get; set; } = true;
+ public bool IsBasePackage { get; set; }
+ public bool SupportsDayaPurchase { get; set; }
+ public bool SupportsDirectPurchase { get; set; } = true;
+ public long ActivationFee { get; set; }
+ public decimal DiscountMultiplier { get; set; } = 2.0m;
+ public decimal MagicWalletMultiplier { get; set; } = 2.5m;
+ // === v3: تنظیمات پورسانت per-package ===
+ public int MaxBalancesPerLeg { get; set; } = 300; // نقرهای=۳۰
+ public int MaxNetworkLevel { get; set; } = 15;
+ // === v3: سقف کیفپول جادویی per-package ===
+ public long MagicWalletMaxDeposit { get; set; } = 1_000_000_000;
+ public long MagicWalletMaxCredit { get; set; } = 2_500_000_000;
+
+ public virtual ICollection<PackageFeature> PackageFeatures { get; set; }
EF Config: PackageConfiguration.cs
- حداکثر یک
IsBasePackage = true(Index filter) - Precision for decimal fields
T1.2 — ایجاد PackageFeature Entity
فایل جدید: CMS/src/CMSMicroservice.Domain/Entities/PackageFeature.cs
public class PackageFeature : BaseAuditableEntity
{
public long PackageId { get; set; }
public virtual Package Package { get; set; }
public long ClubFeatureId { get; set; }
public virtual ClubFeature ClubFeature { get; set; }
public bool IsIncluded { get; set; } = true;
}
T1.3-T1.6 — اضافه PackageId به entityها
| Entity | فیلد | Required? | توضیح | v3? |
|---|---|---|---|---|
| ClubMembership | long? PackageId |
nullable (بعد migration → required) | آخرین پکیج | |
| ClubMembershipCycle | long PackageId |
required | پکیج این چرخه | |
| WeeklyCommissionPool | long PackageId |
required + Unique(WeekDefId, PkgId) | Pool هر پکیج | |
| UserCommissionPayout | long? PackageId |
nullable + Unique(UserId, WeekId, PkgId) | ردیابی | 🔄 |
| NetworkWeeklyBalance | long PackageId |
required + Unique(UserId, WeekId, PkgId) | تعادل per-package | 🆕 |
T1.7 — حذف SystemConstants (v3: ۷ ثابت)
فایل: CMS/src/CMSMicroservice.Domain/Common/SystemConstants.cs
- public const long BasePackageAmount = 56_000_000;
- public const long DayaLoanAmount = 56_000_000;
- public const long ClubActivationFee = 25_200_000;
- public const long ClubMembershipGiftValue = 25_200_000;
- public const decimal MagicWalletMultiplier = 2.5m;
- // === v3: انتقال به Package entity ===
- public const int CommissionMaxWeeklyBalancesPerLeg = 300;
- public const int CommissionMaxNetworkLevel = 15;
⚠️ قبل از حذف: grep تمام مصرفکنندهها → جایگزین با
Package.Property
⚠️ v3:CommissionMaxWeeklyBalancesPerLegوCommissionMaxNetworkLevelهم باید per-package شوند
T1.8 — Database Migration
dotnet ef migrations add AddPackageBasedSystem
شامل:
- ستونهای جدید Package
- جدول PackageFeatures
- FKها در 4 entity
- Unique constraint
T1.9 — Data Migration Script
-- 1. بروزرسانی پکیج فعلی (ID=4 → اضافه فیلدهای جدید)
UPDATE "CMS"."Packages" SET
"SortOrder" = 2,
"IsActive" = true,
"IsBasePackage" = true,
"SupportsDayaPurchase" = true,
"SupportsDirectPurchase" = true,
"ActivationFee" = 25200000,
"DiscountMultiplier" = 2.0,
"MagicWalletMultiplier" = 2.5,
-- v3: تنظیمات پورسانت
"MaxBalancesPerLeg" = 300,
"MaxNetworkLevel" = 15,
"MagicWalletMaxDeposit" = 1000000000,
"MagicWalletMaxCredit" = 2500000000
WHERE "Id" = 4;
-- 2. Link existing data to base package
UPDATE "CMS"."ClubMemberships" SET "PackageId" = 4 WHERE "PackageId" IS NULL;
UPDATE "CMS"."ClubMembershipCycles" SET "PackageId" = 4 WHERE "PackageId" IS NULL;
UPDATE "CMS"."WeeklyCommissionPools" SET "PackageId" = 4 WHERE "PackageId" IS NULL;
UPDATE "CMS"."UserCommissionPayouts" SET "PackageId" = 4 WHERE "PackageId" IS NULL;
-- v3: NetworkWeeklyBalance هم PackageId میگیره
UPDATE "CMS"."NetworkWeeklyBalances" SET "PackageId" = 4 WHERE "PackageId" IS NULL;
-- 3. Seed Silver package (شامل فیلدهای v3)
INSERT INTO "CMS"."Packages" (..., "MaxBalancesPerLeg", "MaxNetworkLevel",
"MagicWalletMaxDeposit", "MagicWalletMaxCredit", ...)
VALUES ('پکیج نقرهای', 5600000, ..., 30, 15, 100000000, 250000000, ...);
T1.10 — بروزرسانی Protoها
| Proto File | تغیر | v3? |
|---|---|---|
| package.proto | فیلدهای جدید Package message (۱۱ فیلد) | 🔄 |
| clubmembership.proto | package_id در request/response | |
| commission.proto | package_id + package_title در ۴ message |
🆕 |
| commission.proto | Message جدید: CustomerCommissionPackageSummary |
🆕 |
| commission.proto | فیلتر package_id در Requestها |
🆕 |
T1.11 — اضافه PackageId به NetworkWeeklyBalance (🆕 v3)
فایل: CMS/src/CMSMicroservice.Domain/Entities/NetworkWeeklyBalance.cs
+ public long PackageId { get; set; }
+ public virtual Package Package { get; set; }
EF Config: اضافه Unique Index:
builder.HasIndex(e => new { e.UserId, e.WeekDefinitionId, e.PackageId }).IsUnique();
builder.HasOne(e => e.Package).WithMany().HasForeignKey(e => e.PackageId);
⚠️ تاثیر حجم: رکوردهای تعادل ×N (تعداد پکیج). مثلاً ۱۰۰۰ کاربر × ۲ پکیج = ۲۰۰۰ رکورد هفتگی
T1.12 — Data Migration: NetworkWeeklyBalance (🆕 v3)
-- رکوردهای موجود → پکیج پایه
UPDATE "CMS"."NetworkWeeklyBalances"
SET "PackageId" = (SELECT "Id" FROM "CMS"."Packages" WHERE "IsBasePackage" = true LIMIT 1)
WHERE "PackageId" IS NULL;
مرحله ۲ — منطق کسبوکار
⏱️ ۴ روز | وابستگی: مرحله ۱ | ریسک: بالا (رگرسیون)
T2.1 — Generic Verify Handler
هدف: ادغام VerifyGolden + VerifyBase + VerifyGeneric → یک handler
الگوریتم:
1. دریافت TransactionId از request
2. خواندن Transaction → PackageId → Package entity
3. verify با درگاه (ZarinPal/BFF/...)
4. اگر موفق:
a. wallet.Balance += Package.Price
b. wallet.DiscountBalance += Package.Price × Package.DiscountMultiplier
c. ساخت WalletChangeLog (Balance)
d. ساخت WalletChangeLog (DiscountBalance)
e. ساخت UserPackagePurchase record
f. اگر اولین خرید: JoinNetwork
g. بروزرسانی ClubMembershipCycle.PackageId
5. return success + receipt
T2.2 — Generic Purchase Handler
هدف: ادغام PurchaseGolden + PurchasePackage + InitiateBase → یک handler
تغییرات:
- حذف فیلتر
Title.Contains("طلایی") - حذف
BasePackageId = 4 - خواندن Package entity از DB بر اساس
request.PackageId - Gateway URL + Amount از Package.Price
T2.3-T2.4 — ActivateClubMembership بهبود
تغییرات:
- var features = await GetAllFeatureIds(); // همه فیچرها
+ var features = await GetPackageFeatures(packageId); // فیچرهای پکیج
- membership.PackageAmount = SystemConstants.BasePackageAmount;
+ membership.PackageAmount = package.Price;
- var activationFee = SystemConstants.ClubActivationFee;
+ var activationFee = package.ActivationFee;
T2.5-T2.6 — Re-Purchase Logic
EXIT Magic Mode — تغییرات:
wallet.WalletMode = WalletMode.Normal;
wallet.MagicCompletedAt = DateTime.UtcNow;
cycle.MagicCompletedAt = DateTime.UtcNow;
+ user.PackagePurchaseMethod = PackagePurchaseMethod.None;
+ membership.IsActive = false;
+ cycle.IsCurrentCycle = false;
Guard تغییرات:
- if (user.PackagePurchaseMethod != PackagePurchaseMethod.None)
- throw new RpcException("قبلاً پکیج خریداری شده");
+ if (user.PackagePurchaseMethod != PackagePurchaseMethod.None
+ && !HasCompletedMagicCycle(membership))
+ throw new RpcException("چرخه جاری هنوز تکمیل نشده");
T2.7 — JWT Claims جدید
claims.Add("HasPurchasedPackage", "true");
+ claims.Add("CanRepurchase", HasCompletedMagicCycle(membership).ToString());
+ claims.Add("PackageId", membership.PackageId?.ToString() ?? "");
+ claims.Add("PackageTitle", package?.Title ?? "");
مرحله ۳ — محاسبه پورسانت (موازی با مرحله ۲)
⏱️ ۴ روز (v3: +۱) | وابستگی: مرحله ۱ | ریسک: بحرانی (مالی)
T3.1-T3.2 — SPs + PackageId + پارامترهای داینامیک (🔄 v3)
-- sp_CalculateWeeklyBalances — v3: حذف hardcode
ALTER PROCEDURE sp_CalculateWeeklyBalances
@WeekDefinitionId BIGINT,
@PackageId BIGINT,
@MaxBalancesPerLeg INT, -- v3: از Package entity (نه ۳۰۰ hardcode!)
@MaxNetworkLevel INT -- v3: از Package entity (نه ۱۵ hardcode!)
AS
BEGIN
-- فیلتر: فقط کاربرانی که این پکیج را دارند
-- carryover: فقط رکوردهای PackageId = @PackageId
-- cap: از @MaxBalancesPerLeg (نه ۳۰۰)
-- depth: CTE تا @MaxNetworkLevel (نه ۱۵)
INSERT INTO "CMS"."NetworkWeeklyBalances" ("PackageId", ...)
SELECT @PackageId, ...
FROM "CMS"."UserWallets" w
INNER JOIN "CMS"."ClubMemberships" m ON m."UserId" = w."UserId"
WHERE m."PackageId" = @PackageId
AND m."IsActive" = true;
END;
T3.3 — Loop Service (🔄 v3: ارسال تنظیمات پکیج)
// WeeklyCommissionCalculationService.cs
var activePackages = await _context.Packages
.Where(p => p.IsActive && !p.IsDeleted)
.ToListAsync();
foreach (var package in activePackages)
{
_logger.LogInformation(
"Calculating commission for package {Id}: {Title} " +
"(MaxBalances={Max}, MaxLevel={Level})",
package.Id, package.Title,
package.MaxBalancesPerLeg, package.MaxNetworkLevel);
// v3: پاس دادن تنظیمات پکیج
await strategy.CalculateWeeklyBalancesAsync(
weekId, package.Id,
package.MaxBalancesPerLeg, package.MaxNetworkLevel);
await strategy.CalculateWeeklyPoolAsync(weekId, package.Id);
}
T3.4 — OrmCommissionCalculationStrategy (🔄 v3)
تغییرات:
- var maxBalances = SystemConstants.CommissionMaxWeeklyBalancesPerLeg; // 300
- var maxLevel = SystemConstants.CommissionMaxNetworkLevel; // 15
+ // پارامتر از بیرون — per-package
+ int maxBalances = maxBalancesPerLeg; // e.g., نقرهای=30, پایه=300
+ int maxLevel = maxNetworkLevel;
- // فیلتر کاربران
+ // فیلتر کاربران بر اساس پکیج
+ .Where(m => m.PackageId == packageId && m.IsActive)
- // carryover
+ // carryover: فقط رکوردهای همان PackageId
+ .Where(b => b.PackageId == packageId && b.WeekDefinitionId == prevWeekId)
T3.5 — SpCommissionCalculationStrategy (🆕 v3)
// قبل: فقط WeekDefinitionId
await connection.ExecuteAsync("CMS.sp_CalculateWeeklyBalances",
new { WeekDefinitionId = weekId, ForceRecalculate = true });
// بعد (v3): پکیج + تنظیمات داینامیک
await connection.ExecuteAsync("CMS.sp_CalculateWeeklyBalances",
new {
WeekDefinitionId = weekId,
PackageId = package.Id,
MaxBalancesPerLeg = package.MaxBalancesPerLeg,
MaxNetworkLevel = package.MaxNetworkLevel,
ForceRecalculate = true
});
T3.6 — Carryover per-package (🆕 v3)
⚠️ بحرانی: week-shifting باید فقط رکوردهای همان PackageId را shift کند
هفته ۱۰ → هفته ۱۱:
علی: carryover_پایه = {Left: surplus, Right: surplus} ← جداگانه
علی: carryover_نقرهای = {Left: 0, Right: 0} ← جداگانه
✖ اشتباه: قاطی کردن carryover پایه و نقرهای!
✔ صحیح: هر PackageId فقط carryover خودش را میبینه
⚠️ نکته بحرانی
پورسانت = پول واقعی. هر تغییر در SPs باید:
- ابتدا در staging با داده واقعی تست شود
- نتایج قبل و بعد مقایسه شوند
- Rollback plan آماده باشد
- در production ابتدا read-only اجرا شود (بدون commit)
مرحله ۴ — UI (FrontOffice + BackOffice)
⏱️ ۵ روز (v3: +۲) | وابستگی: مرحله ۲ + ۳ | ریسک: متوسط
T4.1 — کاشیهای پکیج داینامیک
فایل: FrontOffice/src/.../Pages/Package/Packages.razor
@* قبل: hardcoded *@
@* بعد: *@
@foreach (var package in _packages.OrderBy(p => p.SortOrder))
{
<PackageCard Package="@package"
OnPurchase="StartPurchase"
ShowFeatures="true"
ShowPV="true" />
}
T4.2 — مودال پرداخت شرطی
@if (_selectedPackage.SupportsDirectPurchase)
{
<MudButton OnClick="PayOnline">پرداخت آنلاین</MudButton>
}
@if (_selectedPackage.SupportsDayaPurchase)
{
<MudButton OnClick="PayDaya">اقساط دایا</MudButton>
}
T4.3 — MyPackages + Re-Purchase
@if (_canRepurchase)
{
<MudAlert Severity="Severity.Success">
🎉 چرخه جادویی تکمیل شد! میتوانید پکیج جدید بخرید.
</MudAlert>
<MudButton Href="/packages">خرید پکیج جدید</MudButton>
}
else
{
<MagicWalletProgress Wallet="@_wallet" Cycle="@_currentCycle" />
}
T4.8 — FrontOffice: CommissionDashboard per-package (🆕 v3)
فایل: FrontOffice/src/.../Pages/Commission/CommissionDashboardPage.razor
@* v3: کارتهای خلاصه بر اساس پکیج *@
<MudGrid>
@foreach (var summary in _packageSummaries)
{
<MudItem xs="12" md="6">
<MudCard>
<MudCardHeader>@summary.PackageTitle</MudCardHeader>
<MudCardContent>
<p>زیرمجموعه: @summary.DownlineCount نفر</p>
<p>تیم اول: @summary.LeftLegMembers | تیم دوم: @summary.RightLegMembers</p>
<p>تعادل: @summary.TotalBalances</p>
<p>💰 پاداش: @summary.CommissionFormatted</p>
</MudCardContent>
</MudCard>
</MudItem>
}
</MudGrid>
<MudAlert>📦 مجموع پاداش هفته: @_totalCommission</MudAlert>
T4.9 — FrontOffice: WeeklyBalance per-package (🆕 v3)
تعادل تیم اول/دوم به تفکیک هر پکیج نمایش داده شود
T4.10-T4.12 — BackOffice: گزارشهای پورسانت per-package (🆕 v3)
تغییرات مشترک:
- اضافه dropdown فیلتر پکیج (همه / پایه / نقرهای / ...)
- اضافه ستون پکیج در جدولها
- CSV export شامل ستون پکیج
| صفحه | تغییر |
|---|---|
| Commission Dashboard | فیلتر + خلاصه per-package |
| Weekly Reports | فیلتر + CSV per-package |
| Balances Report | فیلتر + ستون پکیج |
| User Payouts | ستون پکیج + فیلتر |
T4.13 — BackOffice: Package CRUD + Quick Access فیچرها (🆕 v3)
ادمین موقع ساخت/ویرایش پکیج، فیچرها را با checkbox در همان فرم تعیین کند
@* در PackageCreateDialog / PackageEditDialog: *@
<MudText Typo="Typo.h6">فیچرهای پکیج</MudText>
@foreach (var feature in _allFeatures)
{
<MudCheckBox @bind-Checked="feature.IsIncluded" Label="@feature.Title" />
}
مرحله ۵ — تست و استقرار
⏱️ ۳ روز (v3: +۱) | وابستگی: مرحله ۴
Checklist تست
خرید + فعالسازی:
- خرید پکیج نقرهای (ZarinPal)
- خرید پکیج پایه (ZarinPal)
- خرید پکیج پایه (Daya Loan)
- خرید پکیج پایه (Manual Payment)
- فعالسازی باشگاه با پکیج نقرهای → فیچرهای محدود
- فعالسازی باشگاه با پکیج پایه → همه فیچرها
چرخه Magic + خرید مجدد:
- تکمیل چرخه Magic → ریست وضعیت
- خرید مجدد بعد تکمیل چرخه (همان پکیج)
- خرید مجدد با پکیج متفاوت (پایه → نقرهای)
پورسانت per-package (v3):
- Commission Pool جداگانه هر پکیج
- تعادل per-package: MaxBalancesPerLeg متفاوت (پایه=۳۰۰, نقرهای=۳۰)
- Carryover مجزا: shift فقط رکوردهای همان PackageId
- SP پارامترها صحیح: @MaxBalancesPerLeg و @MaxNetworkLevel از Package
- NetworkWeeklyBalance رکوردها: ۲ پکیج = ۲× رکورد
گزارش per-package (v3):
- FO: مشتری کارتهای خلاصه per-package را میبیند
- FO: مجموع پاداش = جمع همه پکیجها
- BO: فیلتر dropdown پکیج کار میکند
- BO: CSV export شامل ستون پکیج
Migration + سایر:
- Data Migration — PackageId در رکوردهای قبلی (شامل NetworkWeeklyBalance)
- JWT claims جدید (CanRepurchase, PackageId)
- UI: کاشیهای داینامیک FrontOffice
- UI: ماتریس فیچر + Quick Access BackOffice
- Rollback: بدون data loss
📅 تقویم پیشنهادی (v3)
| هفته | روز | تسک |
|---|---|---|
| هفته ۱ | روز ۱ | مرحله ۰: فیکس ۴ باگ |
| روز ۲-۳ | مرحله ۱: Package entity (۱۱ فیلد) + PackageFeature | |
| روز ۴-۵ | مرحله ۱: FKها + NetworkWeeklyBalance + Migration | |
| هفته ۲ | روز ۶-۷ | مرحله ۲: Generic handlers + re-purchase |
| روز ۶-۸ | مرحله ۳: SP params + carryover per-package (موازی) | |
| روز ۸-۱۰ | مرحله ۲: Guards + JWT + Manual | |
| هفته ۳ | روز ۱۱-۱۲ | مرحله ۴: FrontOffice UI + گزارش per-package |
| روز ۱۳-۱۴ | مرحله ۴: BackOffice UI + گزارش per-package | |
| روز ۱۵-۱۷ | مرحله ۵: تست + deploy |
🔗 ارجاعات
| مستند | محتوا |
|---|---|
| BIZ-PACKAGE-BASED-SYSTEM.md | طراحی فنی — ۴۸+ تغییر (v3) + باگها |
| PACKAGE-TRANSFORMATION-UX.md | تاثیر UX بر فرانتها |
| FEATURE-BACKLOG.md | بکلاگ ۱۲ RPC آماده |
| GRPC-SERVICES-AUDIT.md | آدیت ۳۴۲ RPC |
آخرین بروزرسانی: ۱۴۰۴/۱۲/۰۶ — v3 (پورسانت per-package + گزارشدهی + carryover)