Refactor ReportsPage to improve data filtering and calculations
- Replaced direct filtering of VPS data with a more structured approach using a Map for account-level grouping. - Enhanced payment and debit calculations to account for both direct and account-level entries. - Introduced logic to calculate total expenses based on monthly and daily rates when no payments or debits are found. - Removed unused monthKey import for cleaner code.
This commit is contained in:
+79
-30
@@ -3,7 +3,6 @@ import {
|
|||||||
convertCurrency,
|
convertCurrency,
|
||||||
downloadTextFile,
|
downloadTextFile,
|
||||||
formatCurrency,
|
formatCurrency,
|
||||||
monthKey,
|
|
||||||
toCsv,
|
toCsv,
|
||||||
vpsStatusLabel,
|
vpsStatusLabel,
|
||||||
} from '../lib/utils'
|
} from '../lib/utils'
|
||||||
@@ -37,36 +36,86 @@ export function ReportsPage({ db, settings, ratesData }) {
|
|||||||
return `${filters.month}-${String(lastDay).padStart(2, '0')}`
|
return `${filters.month}-${String(lastDay).padStart(2, '0')}`
|
||||||
})() : '')
|
})() : '')
|
||||||
|
|
||||||
return db.vps
|
const filteredVps = (db.vps || []).filter((vps) => {
|
||||||
.filter((vps) => {
|
const byProvider = !filters.providerId || vps.providerId === filters.providerId
|
||||||
const byProvider = !filters.providerId || vps.providerId === filters.providerId
|
const byCountry =
|
||||||
const byCountry =
|
!filters.country || vps.country?.toLowerCase().includes(filters.country.toLowerCase())
|
||||||
!filters.country || vps.country?.toLowerCase().includes(filters.country.toLowerCase())
|
return byProvider && byCountry
|
||||||
return byProvider && byCountry
|
})
|
||||||
})
|
|
||||||
.map((vps) => {
|
const vpsByAccount = new Map()
|
||||||
const provider = db.providers.find((item) => item.id === vps.providerId)
|
for (const v of filteredVps) {
|
||||||
const payments = db.payments
|
const aid = v.providerAccountId || ''
|
||||||
.filter((item) => item.vpsId === vps.id && item.type !== 'provider_balance_topup')
|
if (!vpsByAccount.has(aid)) vpsByAccount.set(aid, [])
|
||||||
.filter((item) => !dateFrom || !dateTo || isDateInRange(item.date, dateFrom, dateTo))
|
vpsByAccount.get(aid).push(v)
|
||||||
const debits = db.balanceLedger
|
}
|
||||||
.filter((item) => item.vpsId === vps.id && item.direction === 'debit')
|
|
||||||
.filter((item) => !dateFrom || !dateTo || isDateInRange(item.date, dateFrom, dateTo))
|
return filteredVps.map((vps) => {
|
||||||
const totalPayments = payments.reduce((acc, item) => acc + Number(item.amount || 0), 0)
|
const provider = db.providers.find((item) => item.id === vps.providerId)
|
||||||
const totalDebits = debits.reduce((acc, item) => acc + Number(item.amount || 0), 0)
|
const vpsIdNorm = (id) => (id == null || id === '' ? '' : String(id))
|
||||||
const total = totalPayments + totalDebits
|
|
||||||
return {
|
const paymentsDirect = (db.payments || []).filter(
|
||||||
providerId: vps.providerId,
|
(item) =>
|
||||||
provider: provider?.name || '-',
|
vpsIdNorm(item.vpsId) === vps.id &&
|
||||||
vps: vps.dns || vps.ip,
|
item.type !== 'provider_balance_topup' &&
|
||||||
ip: vps.ip,
|
(!dateFrom || !dateTo || isDateInRange(item.date, dateFrom, dateTo)),
|
||||||
country: vps.country || '',
|
)
|
||||||
city: vps.city || '',
|
const singleVpsInAccount = (vpsByAccount.get(vps.providerAccountId || '') || []).length === 1
|
||||||
status: vps.status,
|
const paymentsAccountLevel = singleVpsInAccount
|
||||||
expense: Number(total.toFixed(2)),
|
? (db.payments || []).filter(
|
||||||
currency: vps.currency || 'USD',
|
(item) =>
|
||||||
|
item.providerAccountId === vps.providerAccountId &&
|
||||||
|
vpsIdNorm(item.vpsId) === '' &&
|
||||||
|
item.type !== 'provider_balance_topup' &&
|
||||||
|
(!dateFrom || !dateTo || isDateInRange(item.date, dateFrom, dateTo)),
|
||||||
|
)
|
||||||
|
: []
|
||||||
|
|
||||||
|
const debitsDirect = (db.balanceLedger || []).filter(
|
||||||
|
(item) =>
|
||||||
|
vpsIdNorm(item.vpsId) === vps.id &&
|
||||||
|
item.direction === 'debit' &&
|
||||||
|
(!dateFrom || !dateTo || isDateInRange(item.date, dateFrom, dateTo)),
|
||||||
|
)
|
||||||
|
const debitsAccountLevel = singleVpsInAccount
|
||||||
|
? (db.balanceLedger || []).filter(
|
||||||
|
(item) =>
|
||||||
|
item.providerAccountId === vps.providerAccountId &&
|
||||||
|
vpsIdNorm(item.vpsId) === '' &&
|
||||||
|
item.direction === 'debit' &&
|
||||||
|
(!dateFrom || !dateTo || isDateInRange(item.date, dateFrom, dateTo)),
|
||||||
|
)
|
||||||
|
: []
|
||||||
|
|
||||||
|
const allPayments = [...paymentsDirect, ...paymentsAccountLevel]
|
||||||
|
const allDebits = [...debitsDirect, ...debitsAccountLevel]
|
||||||
|
const totalPayments = allPayments.reduce((acc, item) => acc + Number(item.amount || 0), 0)
|
||||||
|
const totalDebits = allDebits.reduce((acc, item) => acc + Number(item.amount || 0), 0)
|
||||||
|
let total = totalPayments + totalDebits
|
||||||
|
|
||||||
|
if (total === 0 && (vps.monthlyRate != null && vps.monthlyRate > 0 || vps.dailyRate != null && vps.dailyRate > 0)) {
|
||||||
|
const monthly = Number(vps.monthlyRate) || 0
|
||||||
|
const daily = Number(vps.dailyRate) || 0
|
||||||
|
if (dateFrom && dateTo) {
|
||||||
|
const days = Math.ceil((new Date(dateTo) - new Date(dateFrom)) / (24 * 60 * 60 * 1000)) + 1
|
||||||
|
total = monthly > 0 ? monthly * Math.ceil(days / 30) : daily * days
|
||||||
|
} else {
|
||||||
|
total = monthly > 0 ? monthly : daily * 30
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
providerId: vps.providerId,
|
||||||
|
provider: provider?.name || '-',
|
||||||
|
vps: vps.dns || vps.ip,
|
||||||
|
ip: vps.ip,
|
||||||
|
country: vps.country || '',
|
||||||
|
city: vps.city || '',
|
||||||
|
status: vps.status,
|
||||||
|
expense: Number(total.toFixed(2)),
|
||||||
|
currency: vps.currency || 'USD',
|
||||||
|
}
|
||||||
|
})
|
||||||
}, [db.payments, db.balanceLedger, db.providers, db.vps, filters])
|
}, [db.payments, db.balanceLedger, db.providers, db.vps, filters])
|
||||||
|
|
||||||
const baseCurrency = settings?.[0]?.baseCurrency || 'RUB'
|
const baseCurrency = settings?.[0]?.baseCurrency || 'RUB'
|
||||||
|
|||||||
Reference in New Issue
Block a user