| |
| |
| |
| |
|
|
| import { getLedgerEntries } from './ledger' |
| import type { LedgerEntry } from '../types' |
|
|
| export interface Scope3Contribution { |
| |
| submittedTo: string |
| |
| scope3CertId: string |
| |
| smeName: string |
| |
| natureBeneficiary: string |
| |
| retiredTons: number |
| |
| ledgerEntryId: string |
| |
| retiredAt: string |
| } |
|
|
| export interface Scope3Summary { |
| |
| byOriginator: Record<string, { |
| totalTons: number |
| contributions: Scope3Contribution[] |
| }> |
| |
| byNatureBeneficiary: Record<string, { |
| totalTons: number |
| entryCount: number |
| }> |
| |
| totalScope3Tons: number |
| |
| entryCount: number |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| export function extractScope3FromLedger(entries: LedgerEntry[]): Scope3Contribution[] { |
| return entries |
| .filter((e) => e.category === 'CREDIT_RETIRE') |
| .filter((e) => typeof e.receiverId === 'string' && e.receiverId.startsWith('nature:')) |
| .filter((e) => { |
| const ref = (e.referenceData ?? {}) as Record<string, unknown> |
| return !(ref.is_koc_registered === true || ref.isKocRegistered === true || ref.has_koc_credits === true) |
| }) |
| .map((e) => { |
| const ref = (e.referenceData ?? {}) as Record<string, unknown> |
| const certId = ref.scope3CertId ?? ref.scope3_cert_id |
| if (!certId) return null |
| return { |
| submittedTo: (ref.submittedTo as string) ?? (ref.submitted_to as string) ?? '์์ฒญ ๋ฏธ์ง์ ', |
| scope3CertId: String(certId), |
| smeName: e.senderName, |
| natureBeneficiary: e.receiverName, |
| retiredTons: Number(e.amount), |
| ledgerEntryId: e.id ?? e.transactionId, |
| retiredAt: e.createdAt, |
| } satisfies Scope3Contribution |
| }) |
| .filter((x): x is Scope3Contribution => x !== null) |
| } |
|
|
| export function summarizeScope3(entries: LedgerEntry[]): Scope3Summary { |
| const contributions = extractScope3FromLedger(entries) |
| const byOriginator: Scope3Summary['byOriginator'] = {} |
| const byNatureBeneficiary: Scope3Summary['byNatureBeneficiary'] = {} |
| let totalScope3Tons = 0 |
|
|
| for (const c of contributions) { |
| if (!byOriginator[c.submittedTo]) { |
| byOriginator[c.submittedTo] = { totalTons: 0, contributions: [] } |
| } |
| byOriginator[c.submittedTo].totalTons += c.retiredTons |
| byOriginator[c.submittedTo].contributions.push(c) |
|
|
| if (!byNatureBeneficiary[c.natureBeneficiary]) { |
| byNatureBeneficiary[c.natureBeneficiary] = { totalTons: 0, entryCount: 0 } |
| } |
| byNatureBeneficiary[c.natureBeneficiary].totalTons += c.retiredTons |
| byNatureBeneficiary[c.natureBeneficiary].entryCount += 1 |
|
|
| totalScope3Tons += c.retiredTons |
| } |
|
|
| return { |
| byOriginator, |
| byNatureBeneficiary, |
| totalScope3Tons, |
| entryCount: contributions.length, |
| } |
| } |
|
|
| |
| |
| |
| export async function fetchScope3Summary(campaignId?: string): Promise<Scope3Summary> { |
| try { |
| const entries = await getLedgerEntries({ campaignId, limit: 500 }) |
| return summarizeScope3(entries) |
| } catch { |
| return { |
| byOriginator: {}, |
| byNatureBeneficiary: {}, |
| totalScope3Tons: 0, |
| entryCount: 0, |
| } |
| } |
| } |
|
|