Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP table id_address_mapping;
24 changes: 9 additions & 15 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@ model allocator_client_stats_daily {
}

model clients_stats_daily {
date DateTime
clients_with_active_deals Int
clients_who_have_dc_and_deals Int
total_remaining_clients_datacap BigInt
date DateTime
clients_with_active_deals Int
clients_who_have_dc_and_deals Int
total_remaining_clients_datacap BigInt

@@id(date)
}
Expand Down Expand Up @@ -342,12 +342,6 @@ model client_report_cid_sharing {
unique_cid_count Int
}

model id_address_mapping {
id String @id
address String @unique
create_date DateTime @default(now())
}

model client_report_check_result {
id String @id @default(uuid()) @db.Uuid
create_date DateTime @default(now())
Expand Down Expand Up @@ -604,16 +598,16 @@ model storage_provider_url_finder_metric {
}

model storage_provider_url_finder_metric_value {
id String @id @default(uuid())
id String @id @default(uuid())
provider String
metric_id String
snapshot_id String

metric storage_provider_url_finder_metric @relation(fields: [metric_id], references: [id])
storage_provider_daily_snapshot storage_provider_url_finder_daily_snapshot? @relation(fields: [snapshot_id], references: [id])

value Float?
tested_at DateTime?
value Float?
tested_at DateTime?

@@unique([provider, metric_id, tested_at])
@@index([provider])
Expand All @@ -624,8 +618,8 @@ model storage_provider_url_finder_metric_value {
model storage_provider_url_finder_daily_snapshot {
id String @id @default(uuid())
provider String
snapshot_date DateTime
tested_at DateTime
snapshot_date DateTime
tested_at DateTime
result_code StorageProviderUrlFinderMetricResultCodeType

metric_values storage_provider_url_finder_metric_value[]
Expand Down
2 changes: 1 addition & 1 deletion prismaDmob/sql/getAllocatorsFull.sql
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ select "verifier"."addressId"
"verifier"."createdAtHeight" as "createdAtHeight",
"verifier"."issueCreateTimestamp" as "issueCreateTimestamp",
"verifier"."createMessageTimestamp" as "createMessageTimestamp",
"verifier"."initialAllowance" - "verifier"."allowance" as "remainingDatacap",
"verifier"."allowance" as "remainingDatacap",
(select count(distinct "verified_client"."id")::int from "verified_client"
where "verified_client"."verifierAddressId" = "verifier"."addressId") as "verifiedClientsCount",
coalesce(sum("verifier_allowance"."allowance")
Expand Down
32 changes: 32 additions & 0 deletions src/controller/allocators/allocators.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { AllocatorReportChecksService } from 'src/service/allocator-report-check
import { AllocatorScoringService } from 'src/service/allocator-scoring/allocator-scoring.service';
import { AllocatorService } from 'src/service/allocator/allocator.service';
import {
AllocationByAllocator,
AllocatorAuditOutcomesData,
AllocatorAuditStatesData,
AllocatorAuditTimesByMonthData,
Expand Down Expand Up @@ -55,6 +56,7 @@ import {
GetDatacapFlowDataResponse,
GetWeekAllocatorsWithSpsComplianceRequest,
GetWeekAllocatorsWithSpsComplianceRequestData,
GetAllocationsByAllocatorRequest,
} from './types.allocators';

const dashboardStatisticsTitleDict: Record<
Expand Down Expand Up @@ -385,6 +387,36 @@ export class AllocatorsController extends FilPlusEditionControllerBase {
);
}

@Get(':allocatorId/allocations')
@ApiOperation({
summary: 'Get allocations over time for allocator grouped by week or month',
})
@ApiOkResponse({
description:
'List of allocations over time for allocator grouped by week or month',
type: AllocationByAllocator,
isArray: true,
})
public async getAllocationsByAllocator(
@Param('allocatorId') allocatorId: string,
@Query() query: GetAllocationsByAllocatorRequest,
): Promise<AllocationByAllocator[]> {
query.groupBy ??= 'week';

if (query.groupBy && !['week', 'month'].includes(query.groupBy)) {
throw new BadRequestException(
`Invalid groupBy value: ${query.groupBy}, must be 'week' or 'month'`,
);
}

return this.allocatorService.getAllocationsByAllocator(
allocatorId,
query.groupBy,
stringToBool(query.showEmptyPeriods) ?? false,
stringToBool(query.showAllocations) ?? false,
);
}

@Get('/statistics')
@ApiOperation({
summary: 'Get list of statistics regarding allocators',
Expand Down
23 changes: 23 additions & 0 deletions src/controller/allocators/types.allocators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -417,3 +417,26 @@ export class GetAllocatorsStatisticsRequest extends PartialType(
) {}

export class GetAllocatorVerifiedClientsRequest extends PaginationSortingInfoRequest {}

export class GetAllocationsByAllocatorRequest {
@ApiPropertyOptional({
description: 'Group by week or month; default is week',
enum: ['week', 'month'],
example: 'week',
})
groupBy?: 'week' | 'month';

@ApiPropertyOptional({
description:
'Flag to include periods with no allocations; default is false',
type: Boolean,
})
showEmptyPeriods?: stringifiedBool;

@ApiPropertyOptional({
description:
'Flag to return allocation details for each period; default is false',
type: Boolean,
})
showAllocations?: stringifiedBool;
}
20 changes: 4 additions & 16 deletions src/controller/clients/clients.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,23 +105,11 @@ export class ClientsController extends ControllerBase {
0n,
);

const dmobDbClientName =
clientData.find((c) => c.name)?.name?.trim() ?? null;
const dmobDbClientOrgName =
clientData.find((c) => c.orgName)?.orgName?.trim() ?? null;

// Prefer bookkeeping client name over dmob db names
const clientName =
(
await this.clientService.getClientBookkeepingInfo(
clientData[0].addressId,
)
)?.clientName ||
dmobDbClientName ||
dmobDbClientOrgName;

return {
name: clientName,
name: await this.clientService.getClientName(
clientData[0].addressId,
clientData,
),
stats: clientProviderDistribution.map((provider) => ({
provider: provider.provider,
total_deal_size: provider.total_deal_size,
Expand Down
15 changes: 5 additions & 10 deletions src/service/allocator-report/allocator-report.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,18 +132,13 @@ export class AllocatorReportService {
client.addressId,
);

const clientName =
(client.name?.trim() ||
clientData?.find((c) => c.name)?.name?.trim()) ??
null;

const clientOrgName =
clientData?.find((c) => c.orgName)?.orgName?.trim() ?? null;

return {
client_id: client.addressId,
name:
bookkeepingInfo?.clientName || clientName || clientOrgName,
name: await this.clientService.getClientName(
client.addressId,
clientData,
bookkeepingInfo,
),
allocators: clientData?.map((c) => c.verifierAddressId) ?? null,
allocations_number: client.allowanceArray.length,
application_url:
Expand Down
113 changes: 108 additions & 5 deletions src/service/allocator/allocator.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import { PrismaService } from 'src/db/prisma.service';
import { PrismaDmobService } from 'src/db/prismaDmob.service';
import { Cacheable } from 'src/utils/cacheable';
import {
AllocationByAllocator,
AllocationByAllocatorNewAllocation,
AllocatorAuditOutcome,
AllocatorAuditOutcomesData,
AllocatorAuditStatesData,
Expand Down Expand Up @@ -73,6 +75,7 @@ import { edition5AllocatorAuditOutcomesData } from './resources/edition5Allocato
import { edition5AllocatorAuditStatesData } from './resources/edition5AllocatorAuditStatesData';
import { edition5AllocatorAuditTimesByRoundData } from './resources/edition5AllocatorAuditTimesByRoundData';
import { edition5AllocatorDatacapFlowData } from './resources/edition5AllocatorDatacapFlowData';
import { ClientService } from '../client/client.service';

const registryEntryWithApproveDateSchema = z.object({
history: z.object({
Expand Down Expand Up @@ -110,6 +113,7 @@ export class AllocatorService {
private readonly histogramHelper: HistogramHelperService,
private readonly storageProviderService: StorageProviderService,
private readonly configService: ConfigService,
private readonly clientService: ClientService,
@Inject(CACHE_MANAGER) private cacheManager: Cache,
) {}

Expand Down Expand Up @@ -412,6 +416,10 @@ export class AllocatorService {
case 'PENDING':
return AllocatorAuditOutcome.pending;

case 'UNKNOWN':
case 'unknown':
return AllocatorAuditOutcome.unknown;

default:
this.logger.warn(
`Allocator ${allocatorId} has unknown audit outcome ${outcome}, please investigate`,
Expand Down Expand Up @@ -1197,22 +1205,117 @@ export class AllocatorService {
]);

const totalAllocatorsCount = allAllocators.length;
if (totalAllocatorsCount === 0) return 0;

const matchingAllocatorsCount = currentlyMatchingAllocators.length;
return matchingAllocatorsCount / totalAllocatorsCount;
}

public async getAllocationsByAllocator(
allocatorId: string,
groupBy: 'week' | 'month',
returnEmptyPeriods = false,
returnAllocations = false,
): Promise<AllocationByAllocator[]> {
const clientAllocationsWeekly =
await this.prismaService.client_allocator_distribution_weekly.findMany({
where: {
allocator: allocatorId,
},
orderBy: {
week: 'asc',
},
});

if (clientAllocationsWeekly?.length === 0) return [];
let date = clientAllocationsWeekly[0].week;

if (totalAllocatorsCount === 0) {
return 0;
// align to the start of the next week or next month
if (groupBy === 'week') {
if (date.getUTCDay() !== 1) {
date = new Date(
date.getTime() + ((8 - date.getUTCDay()) % 7) * 24 * 60 * 60 * 1000,
);
}
} else {
if (date.getUTCDate() !== 1) {
date = new Date(
Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, 1),
);
}
}

const matchingAllocatorsCount = currentlyMatchingAllocators.length;
let sumOfAllocationsToDate = 0n;
const clientsToDate = new Set<string>();
const newClients = new Set<string>();
let newAllocations: AllocationByAllocatorNewAllocation[] = [];
const allocationsPerClient: Record<string, bigint> = {};
const result: AllocationByAllocator[] = [];

return matchingAllocatorsCount / totalAllocatorsCount;
const updateResult = async () => {
if (!returnEmptyPeriods && !newAllocations.length) return;

result.push({
date: date,
totalAllocationsToDate: sumOfAllocationsToDate,
clientsToDate: Array.from(clientsToDate).map((client) => ({
client: client,
allocationsToDate: allocationsPerClient[client] ?? 0n,
})),
newClients: await Promise.all(
Array.from(newClients).map(async (client) => ({
client: client,
allocationsToDate: allocationsPerClient[client] ?? 0n,
clientName: await this.clientService.getClientName(client),
})),
),
newAllocations: returnAllocations ? newAllocations : null,
});
};

for (let i = 0; i < clientAllocationsWeekly.length; ) {
if (clientAllocationsWeekly[i].week <= date) {
sumOfAllocationsToDate += clientAllocationsWeekly[i].sum_of_allocations;

allocationsPerClient[clientAllocationsWeekly[i].client] =
(allocationsPerClient[clientAllocationsWeekly[i].client] ?? 0n) +
clientAllocationsWeekly[i].sum_of_allocations;

if (!clientsToDate.has(clientAllocationsWeekly[i].client))
newClients.add(clientAllocationsWeekly[i].client);

newAllocations.push({
client: clientAllocationsWeekly[i].client,
allocation: clientAllocationsWeekly[i].sum_of_allocations,
});

clientsToDate.add(clientAllocationsWeekly[i].client);
++i;
} else {
await updateResult();
newClients.clear();
newAllocations = [];

date =
groupBy === 'week'
? new Date(date.getTime() + 7 * 24 * 60 * 60 * 1000) // next week
: new Date( // next month
Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, 1),
);
}
}

if (result.length === 0 || result[result.length - 1].date < date)
await updateResult();

return result;
}

public async getVerifiedClientsByAllocator(allocatorId: string) {
const twoWeeksAgoTimestamp =
Math.floor(Date.now() / 1000) - 14 * 24 * 60 * 60;

const allocatorData = await this.getAllocatorData(allocatorId);

if (!allocatorData) return null;

let allocatorVerifiedClients = [];
Expand Down
Loading
Loading