fix: scope page insights to reporting periods
This commit is contained in:
@@ -9,6 +9,7 @@ import (
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"git.amiirkhl.ir/starcoach-hackathon/zarinpal-analytics-backend/internal/analytics"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
@@ -83,7 +84,7 @@ func (b *PostgreSQLBuilder) build(ctx context.Context, merchantID int64, termina
|
||||
timeContext := BuildTimeContext(b.now(), dataThrough)
|
||||
var latest, previous aggregate
|
||||
var err error
|
||||
if period != nil && module == ModuleTransactions {
|
||||
if period != nil {
|
||||
latest, err = b.aggregateRange(ctx, merchantID, terminalID, period.StartAt, period.EndAt)
|
||||
if err == nil {
|
||||
duration := period.EndAt.Sub(period.StartAt)
|
||||
@@ -108,16 +109,29 @@ func (b *PostgreSQLBuilder) build(ctx context.Context, merchantID int64, termina
|
||||
}
|
||||
evidenceMap := map[string]any{
|
||||
"schemaVersion": "1.0.0", "module": module, "comparisonAvailable": comparisonAvailable,
|
||||
"latest30Days": latest, "previousYearEquivalent": previous,
|
||||
"time": timeContext, "privacy": map[string]any{"aggregateOnly": true, "peerSuppressionApplied": module == ModulePeers},
|
||||
}
|
||||
if period != nil && module == ModuleTransactions {
|
||||
precedingPeriodLabel := ""
|
||||
if period != nil {
|
||||
precedingPeriodLabel, _ = analytics.PrecedingPeriodLabel(period.PeriodType, period.StartAt)
|
||||
evidenceMap["selectedPeriod"] = map[string]any{"periodId": period.PeriodID, "periodType": period.PeriodType, "startAt": period.StartAt, "endAt": period.EndAt, "jalaliLabelFa": period.JalaliLabelFA}
|
||||
evidenceMap["selectedPeriodAggregate"] = latest
|
||||
if comparisonAvailable {
|
||||
evidenceMap["precedingPeriod"] = map[string]any{"jalaliLabelFa": precedingPeriodLabel}
|
||||
evidenceMap["precedingPeriodAggregate"] = previous
|
||||
}
|
||||
} else {
|
||||
evidenceMap["latest30Days"] = latest
|
||||
evidenceMap["previousYearEquivalent"] = previous
|
||||
}
|
||||
if period != nil && module == ModuleTransactions {
|
||||
evidenceMap["statusDistribution"] = map[string]any{
|
||||
"total": latest.Sessions, "paidAwaitingVerification": latest.Unverified, "verified": latest.Verified, "failed": latest.Failed, "reversed": latest.Reversed,
|
||||
"bankSuccessRate": ratio(latest.Paid, latest.Sessions), "verificationCompletionRate": ratio(latest.Verified, latest.Paid), "failureRate": ratio(latest.Failed, latest.Sessions),
|
||||
}
|
||||
evidenceMap["precedingPeriodStatus"] = previous
|
||||
if comparisonAvailable {
|
||||
evidenceMap["precedingPeriodStatus"] = previous
|
||||
}
|
||||
}
|
||||
business, err := b.businessContext(ctx, merchantID, terminalID)
|
||||
if err != nil {
|
||||
@@ -138,8 +152,8 @@ func (b *PostgreSQLBuilder) build(ctx context.Context, merchantID int64, termina
|
||||
return Analysis{}, fmt.Errorf("encoding insight evidence: %w", err)
|
||||
}
|
||||
copy := deterministicCopy(module, latest, previous, comparisonAvailable, timeContext, confidence)
|
||||
if period != nil && module == ModuleTransactions {
|
||||
copy = deterministicTransactionCopy(*period, latest, previous, comparisonAvailable, timeContext, confidence)
|
||||
if period != nil {
|
||||
copy = deterministicPeriodCopy(module, *period, precedingPeriodLabel, latest, previous, comparisonAvailable, timeContext, confidence)
|
||||
}
|
||||
return Analysis{Time: timeContext, Confidence: confidence, Evidence: encoded, Copy: copy, Calendar: calendar}, nil
|
||||
}
|
||||
@@ -311,11 +325,11 @@ func deterministicCopy(module Module, latest, previous aggregate, comparison boo
|
||||
return copy
|
||||
}
|
||||
|
||||
func deterministicTransactionCopy(period PeriodScope, latest, previous aggregate, comparison bool, _ TimeContext, confidence Confidence) Copy {
|
||||
latestBody := fmt.Sprintf("در بازهٔ %s، %d تراکنش ثبت شده است: %d پرداختشده و در انتظار تأیید، %d تأیید نهایی، %d ناموفق و %d برگشتخورده. نرخ موفقیت بانکی %s، تکمیل تأیید %s و نرخ ناموفق %s است.", period.JalaliLabelFA, latest.Sessions, latest.Unverified, latest.Verified, latest.Failed, latest.Reversed, ratioText(latest.Paid, latest.Sessions), ratioText(latest.Verified, latest.Paid), ratioText(latest.Failed, latest.Sessions))
|
||||
pastBody := "برای بازهٔ بلافاصله قبل دادهٔ کافی برای مقایسه وجود ندارد."
|
||||
func deterministicTransactionCopy(period PeriodScope, precedingPeriodLabel string, latest, previous aggregate, comparison bool, _ TimeContext, confidence Confidence) Copy {
|
||||
latestBody := fmt.Sprintf("در %s، %d تراکنش ثبت شده است: %d پرداختشده و در انتظار تأیید، %d تأیید نهایی، %d ناموفق و %d برگشتخورده. نرخ موفقیت بانکی %s، تکمیل تأیید %s و نرخ ناموفق %s است.", period.JalaliLabelFA, latest.Sessions, latest.Unverified, latest.Verified, latest.Failed, latest.Reversed, ratioText(latest.Paid, latest.Sessions), ratioText(latest.Verified, latest.Paid), ratioText(latest.Failed, latest.Sessions))
|
||||
pastBody := fmt.Sprintf("این خلاصه فقط وضعیت %s را نشان میدهد و با دادههای موجود دربارهٔ افزایش یا کاهش نسبت به دورهای دیگر نتیجهگیری نمیکند.", period.JalaliLabelFA)
|
||||
if comparison {
|
||||
pastBody = fmt.Sprintf("در بازهٔ بلافاصله قبل %d تراکنش و %d پرداخت موفق بانکی ثبت شده بود؛ این مقایسه فقط تغییر مشاهدهشده را نشان میدهد و علت آن را مشخص نمیکند.", previous.Sessions, previous.Paid)
|
||||
pastBody = fmt.Sprintf("در %s، %d تراکنش و %d پرداخت موفق بانکی ثبت شده بود؛ این مقایسه فقط تغییر مشاهدهشده را نشان میدهد و علت آن را مشخص نمیکند.", precedingPeriodLabel, previous.Sessions, previous.Paid)
|
||||
}
|
||||
uncertainty := "این جمعبندی فقط الگوی مشاهدهشده در نمودارها را توصیف میکند و علت تغییر وضعیتها را تعیین نمیکند."
|
||||
return Copy{
|
||||
@@ -332,6 +346,38 @@ func deterministicTransactionCopy(period PeriodScope, latest, previous aggregate
|
||||
}
|
||||
}
|
||||
|
||||
func deterministicPeriodCopy(module Module, period PeriodScope, precedingPeriodLabel string, latest, previous aggregate, comparison bool, tc TimeContext, confidence Confidence) Copy {
|
||||
if module == ModuleTransactions {
|
||||
return deterministicTransactionCopy(period, precedingPeriodLabel, latest, previous, comparison, tc, confidence)
|
||||
}
|
||||
|
||||
latestBody := fmt.Sprintf("در %s، %d تراکنش ثبت شد و %d پرداخت با موفقیت انجام شد.", period.JalaliLabelFA, latest.Sessions, latest.Paid)
|
||||
switch module {
|
||||
case ModulePayments:
|
||||
latestBody = fmt.Sprintf("در %s، از %d تراکنش ثبتشده، %d پرداخت موفق و %d پرداخت ناموفق بود.", period.JalaliLabelFA, latest.Sessions, latest.Paid, latest.Failed)
|
||||
case ModuleFees:
|
||||
latestBody = fmt.Sprintf("در %s، مجموع کارمزد ثبتشده %d ریال بود و %d پرداخت موفق انجام شد.", period.JalaliLabelFA, latest.Fees, latest.Paid)
|
||||
case ModulePeers:
|
||||
latestBody = fmt.Sprintf("در %s، کسبوکار شما %d پرداخت موفق از %d تراکنش ثبتشده داشت.", period.JalaliLabelFA, latest.Paid, latest.Sessions)
|
||||
}
|
||||
|
||||
pastBody := fmt.Sprintf("این خلاصه فقط وضعیت %s را نشان میدهد و با دادههای موجود دربارهٔ افزایش یا کاهش نسبت به دورهای دیگر نتیجهگیری نمیکند.", period.JalaliLabelFA)
|
||||
if comparison {
|
||||
direction := "تقریباً مشابه"
|
||||
if latest.Paid > previous.Paid {
|
||||
direction = "بیشتر"
|
||||
} else if latest.Paid < previous.Paid {
|
||||
direction = "کمتر"
|
||||
}
|
||||
pastBody = fmt.Sprintf("تعداد پرداختهای موفق در %s نسبت به %s %s بوده است؛ بهتر است همین روند را در دورهٔ بعد هم بررسی کنید.", period.JalaliLabelFA, precedingPeriodLabel, direction)
|
||||
}
|
||||
|
||||
copy := deterministicCopy(module, latest, previous, comparison, tc, confidence)
|
||||
copy.LatestObserved = Narrative{Headline: "خلاصهٔ این بازه", Body: latestBody, EvidenceID: []string{"latest-volume", "payment-health"}}
|
||||
copy.Past = Narrative{Headline: "مقایسه با بازهٔ قبل", Body: pastBody, EvidenceID: []string{"previous-year-equivalent"}}
|
||||
return copy
|
||||
}
|
||||
|
||||
func score(impact int64, confidence Confidence) int {
|
||||
base := int(math.Min(8000, math.Log10(float64(max(int64(1), impact))+1)*1200))
|
||||
weight := map[Confidence]int{ConfidenceHigh: 10000, ConfidenceMedium: 7500, ConfidenceLow: 4500, ConfidenceInsufficientData: 2000}[confidence]
|
||||
|
||||
Reference in New Issue
Block a user