Fix Get agent balance
This commit is contained in:
@@ -6,9 +6,10 @@ namespace Managing.Application.Abstractions.Services;
|
|||||||
|
|
||||||
public interface IStatisticService
|
public interface IStatisticService
|
||||||
{
|
{
|
||||||
Task<IList<AgentBalanceHistory>> GetAgentBalances(string agentName, DateTime start, DateTime? end = null);
|
Task<AgentBalanceHistory> GetAgentBalances(string agentName, DateTime start, DateTime? end = null);
|
||||||
|
|
||||||
Task<(IList<AgentBalanceHistory> Agents, int TotalCount)> GetBestAgents(DateTime start, DateTime? end = null, int page = 1,
|
Task<(IList<AgentBalanceHistory> Agents, int TotalCount)> GetBestAgents(DateTime start, DateTime? end = null,
|
||||||
|
int page = 1,
|
||||||
int pageSize = 10);
|
int pageSize = 10);
|
||||||
|
|
||||||
List<Trader> GetBadTraders();
|
List<Trader> GetBadTraders();
|
||||||
|
|||||||
@@ -378,14 +378,14 @@ public class StatisticService : IStatisticService
|
|||||||
await _messengerService.SendBadTraders(lastBadTrader);
|
await _messengerService.SendBadTraders(lastBadTrader);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IList<AgentBalanceHistory>> GetAgentBalances(string agentName, DateTime start,
|
public async Task<AgentBalanceHistory> GetAgentBalances(string agentName, DateTime start,
|
||||||
DateTime? end = null)
|
DateTime? end = null)
|
||||||
{
|
{
|
||||||
var effectiveEnd = end ?? DateTime.UtcNow;
|
var effectiveEnd = end ?? DateTime.UtcNow;
|
||||||
string cacheKey = $"AgentBalances_{agentName}_{start:yyyyMMdd}_{effectiveEnd:yyyyMMdd}";
|
string cacheKey = $"AgentBalances_{agentName}_{start:yyyyMMdd}_{effectiveEnd:yyyyMMdd}";
|
||||||
|
|
||||||
// Check if the balances are already cached
|
// Check if the balances are already cached
|
||||||
var cachedBalances = _cacheService.GetValue<IList<AgentBalanceHistory>>(cacheKey);
|
var cachedBalances = _cacheService.GetValue<AgentBalanceHistory>(cacheKey);
|
||||||
|
|
||||||
if (cachedBalances != null)
|
if (cachedBalances != null)
|
||||||
{
|
{
|
||||||
@@ -395,13 +395,10 @@ public class StatisticService : IStatisticService
|
|||||||
var balances = await _agentBalanceRepository.GetAgentBalances(agentName, start, end);
|
var balances = await _agentBalanceRepository.GetAgentBalances(agentName, start, end);
|
||||||
|
|
||||||
// Create a single AgentBalanceHistory with all balances
|
// Create a single AgentBalanceHistory with all balances
|
||||||
var result = new List<AgentBalanceHistory>
|
var result = new AgentBalanceHistory
|
||||||
{
|
|
||||||
new AgentBalanceHistory
|
|
||||||
{
|
{
|
||||||
AgentName = agentName,
|
AgentName = agentName,
|
||||||
AgentBalances = balances.OrderBy(b => b.Time).ToList()
|
AgentBalances = balances.OrderBy(b => b.Time).ToList()
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Cache the results for 5 minutes
|
// Cache the results for 5 minutes
|
||||||
@@ -434,7 +431,8 @@ public class StatisticService : IStatisticService
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get all agents with their balance history
|
// Get all agents with their balance history
|
||||||
var (fetchedAgents, fetchedTotalCount) = await _agentBalanceRepository.GetAllAgentBalancesWithHistory(start, end);
|
var (fetchedAgents, fetchedTotalCount) =
|
||||||
|
await _agentBalanceRepository.GetAllAgentBalancesWithHistory(start, end);
|
||||||
|
|
||||||
// Cache all results for 5 minutes
|
// Cache all results for 5 minutes
|
||||||
_cacheService.SaveValue(cacheKey, (fetchedAgents, fetchedTotalCount), TimeSpan.FromMinutes(5));
|
_cacheService.SaveValue(cacheKey, (fetchedAgents, fetchedTotalCount), TimeSpan.FromMinutes(5));
|
||||||
|
|||||||
@@ -49,7 +49,8 @@ public class AgentBalanceRepository : IAgentBalanceRepository
|
|||||||
$"|> range(start: {start:s}Z" +
|
$"|> range(start: {start:s}Z" +
|
||||||
(end.HasValue ? $", stop: {end.Value:s}Z" : "") +
|
(end.HasValue ? $", stop: {end.Value:s}Z" : "") +
|
||||||
$") " +
|
$") " +
|
||||||
$"|> filter(fn: (r) => r[\"agent_name\"] == \"{agentName}\")";
|
$"|> filter(fn: (r) => r[\"agent_name\"] == \"{agentName}\") " +
|
||||||
|
$"|> pivot(rowKey: [\"_time\"], columnKey: [\"_field\"], valueColumn: \"_value\")";
|
||||||
|
|
||||||
var result = await query.QueryAsync<AgentBalanceDto>(flux, _influxDbRepository.Organization);
|
var result = await query.QueryAsync<AgentBalanceDto>(flux, _influxDbRepository.Organization);
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,15 @@ export interface AgentBalanceWithBalances extends AgentBalanceHistory {
|
|||||||
}>;
|
}>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const FILTERS = [
|
||||||
|
{ label: '24H', value: '24H', days: 1 },
|
||||||
|
{ label: '3D', value: '3D', days: 3 },
|
||||||
|
{ label: '1W', value: '1W', days: 7 },
|
||||||
|
{ label: '1M', value: '1M', days: 30 },
|
||||||
|
{ label: '1Y', value: '1Y', days: 365 },
|
||||||
|
{ label: 'Total', value: 'Total', days: null },
|
||||||
|
]
|
||||||
|
|
||||||
function BestAgents() {
|
function BestAgents() {
|
||||||
const { apiUrl } = useApiUrlStore()
|
const { apiUrl } = useApiUrlStore()
|
||||||
const [data, setData] = useState<AgentBalanceWithBalances[]>([])
|
const [data, setData] = useState<AgentBalanceWithBalances[]>([])
|
||||||
@@ -21,37 +30,52 @@ function BestAgents() {
|
|||||||
const [page, setPage] = useState(1)
|
const [page, setPage] = useState(1)
|
||||||
const [pageSize, setPageSize] = useState(10)
|
const [pageSize, setPageSize] = useState(10)
|
||||||
const [totalPages, setTotalPages] = useState(1)
|
const [totalPages, setTotalPages] = useState(1)
|
||||||
const [expandedAgent, setExpandedAgent] = useState<string | null>(null)
|
const [selectedFilter, setSelectedFilter] = useState('Total')
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setIsLoading(true)
|
setIsLoading(true)
|
||||||
const client = new DataClient({}, apiUrl)
|
const client = new DataClient({}, apiUrl)
|
||||||
const now = new Date()
|
const now = new Date()
|
||||||
const startDate = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 30)
|
|
||||||
|
// Calculate start date based on selected filter
|
||||||
|
const filterObj = FILTERS.find(f => f.value === selectedFilter)
|
||||||
|
let startDate: Date
|
||||||
|
if (filterObj?.days) {
|
||||||
|
// Use the filter's days value to calculate start date
|
||||||
|
startDate = new Date(now.getTime() - filterObj.days * 24 * 60 * 60 * 1000)
|
||||||
|
} else {
|
||||||
|
// For 'Total', fetch from a far past date (e.g., 5 years ago)
|
||||||
|
startDate = new Date(now.getFullYear() - 5, now.getMonth(), now.getDate())
|
||||||
|
}
|
||||||
|
|
||||||
client.data_GetBestAgents(startDate, now, page, pageSize).then((res: BestAgentsResponse) => {
|
client.data_GetBestAgents(startDate, now, page, pageSize).then((res: BestAgentsResponse) => {
|
||||||
setData(res.agents as AgentBalanceWithBalances[] ?? [])
|
setData(res.agents as AgentBalanceWithBalances[] ?? [])
|
||||||
setTotalPages(res.totalPages ?? 1)
|
setTotalPages(res.totalPages ?? 1)
|
||||||
console.log(res)
|
console.log(res)
|
||||||
}).finally(() => setIsLoading(false))
|
}).finally(() => setIsLoading(false))
|
||||||
}, [apiUrl, page, pageSize])
|
}, [apiUrl, page, pageSize, selectedFilter])
|
||||||
|
|
||||||
// Type guard for agentBalances
|
function filterBalancesByRange(agent: AgentBalanceWithBalances) {
|
||||||
function hasAgentBalances(agent: AgentBalanceWithBalances): agent is Required<AgentBalanceWithBalances> {
|
if (!agent.agentBalances || selectedFilter === 'Total') return agent.agentBalances ?? []
|
||||||
return Array.isArray(agent.agentBalances) && agent.agentBalances.length > 0;
|
const days = FILTERS.find(f => f.value === selectedFilter)?.days
|
||||||
|
if (!days) return agent.agentBalances ?? []
|
||||||
|
const now = new Date()
|
||||||
|
const cutoff = new Date(now.getTime() - days * 24 * 60 * 60 * 1000)
|
||||||
|
return agent.agentBalances.filter(b => b.time && new Date(b.time) >= cutoff)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the latest balance for each agent
|
// Get the latest balance for each agent
|
||||||
const latestBalances = data.map(agent => {
|
const latestBalances = data.map(agent => {
|
||||||
if (hasAgentBalances(agent)) {
|
const filteredBalances = filterBalancesByRange(agent)
|
||||||
const lastBalance = agent.agentBalances[agent.agentBalances.length - 1]
|
if (filteredBalances.length > 0) {
|
||||||
|
const lastBalance = filteredBalances[filteredBalances.length - 1]
|
||||||
return {
|
return {
|
||||||
agentName: agent.agentName,
|
agentName: agent.agentName,
|
||||||
originalAgent: agent, // Store the original agent for row details
|
originalAgent: { ...agent, agentBalances: filteredBalances },
|
||||||
...lastBalance
|
...lastBalance
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// fallback: just agentName
|
return { agentName: agent.agentName, originalAgent: { ...agent, agentBalances: filteredBalances } }
|
||||||
return { agentName: agent.agentName, originalAgent: agent }
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
@@ -63,10 +87,20 @@ function BestAgents() {
|
|||||||
{ Header: 'Last Update', accessor: 'time', Cell: ({ value }: any) => value ? new Date(value).toLocaleString() : '' },
|
{ Header: 'Last Update', accessor: 'time', Cell: ({ value }: any) => value ? new Date(value).toLocaleString() : '' },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container mx-auto pt-6">
|
<div className="container mx-auto pt-6">
|
||||||
<GridTile title="Best Agents">
|
<GridTile title="Best Agents">
|
||||||
|
<div className="flex gap-2 mb-3">
|
||||||
|
{FILTERS.map(f => (
|
||||||
|
<button
|
||||||
|
key={f.value}
|
||||||
|
className={`px-2 py-0.5 text-xs rounded ${selectedFilter === f.value ? 'bg-primary text-primary-content' : 'bg-base-200'}`}
|
||||||
|
onClick={() => setSelectedFilter(f.value)}
|
||||||
|
>
|
||||||
|
{f.label}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<progress className="progress progress-primary w-56"></progress>
|
<progress className="progress progress-primary w-56"></progress>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
Reference in New Issue
Block a user