Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: corrected home page merchants metrics source of truth (BAL-3396, BAL-3397) #2968

Merged
merged 4 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from 2 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
Expand Up @@ -166,9 +166,30 @@ export class BusinessReportControllerExternal {
@CurrentProject() currentProjectId: TProjectId,
@Query() { from, to }: BusinessReportMetricsRequestQueryDto,
) {
const { id: customerId } = await this.customerService.getByProjectId(currentProjectId);
const { id: customerId, features } = await this.customerService.getByProjectId(
currentProjectId,
);

return await this.merchantMonitoringClient.getMetrics({ customerId, from, to });
const { totalActiveMerchants, addedMerchantsCount, unmonitoredMerchants } =
await this.businessService.getMerchantMonitoringMetrics({
projectIds: [currentProjectId],
features,
from,
to,
});

const merchantMonitoringMetrics = await this.merchantMonitoringClient.getMetrics({
customerId,
from,
to,
});

return {
...merchantMonitoringMetrics,
totalActiveMerchants,
addedMerchantsCount,
removedMerchantsCount: unmonitoredMerchants,
};
}

@common.Post()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,12 +155,14 @@ export class BusinessControllerExternal {
featureConfig?: TCustomerWithFeatures['features'];
};

const isEnabled = data.state === 'on';
const updatedMetadata = _.merge({}, metadata, {
featureConfig: {
[FEATURE_LIST.ONGOING_MERCHANT_REPORT]: {
enabled: data.state === 'on',
enabled: isEnabled,
reason: data.reason ?? null,
userReason: data.userReason ?? null,
disabledAt: isEnabled ? null : new Date().getTime(),
},
},
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,13 @@ export class BusinessRepository {
...args,
});
}

async count<T extends Prisma.BusinessCountArgs>(
args: Prisma.SelectSubset<T, Prisma.BusinessCountArgs>,
projectIds: TProjectIds,
) {
return await this.prismaService.business.count(
this.scopeService.scopeFindMany(args, projectIds),
);
}
}
105 changes: 103 additions & 2 deletions services/workflows-service/src/business/business.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,19 @@ import {
TCompanyInformation,
} from '@/business/types/business-information';
import { AppLoggerService } from '@/common/app-logger/app-logger.service';
import { FEATURE_LIST, TCustomerFeaturesConfig, TCustomerWithFeatures } from '@/customer/types';
import { env } from '@/env';
import type { PrismaTransaction, TProjectIds } from '@/types';
import { HttpService } from '@nestjs/axios';
import * as common from '@nestjs/common';
import { Injectable } from '@nestjs/common';
import { Business } from '@prisma/client';
import { Business, Prisma } from '@prisma/client';
import { AxiosError } from 'axios';
import { plainToClass } from 'class-transformer';
import dayjs from 'dayjs';
import { lastValueFrom } from 'rxjs';
import { z } from 'zod';
import { BusinessRepository } from './business.repository';
import { TCustomerWithFeatures } from '@/customer/types';

@Injectable()
export class BusinessService {
Expand Down Expand Up @@ -66,6 +68,105 @@ export class BusinessService {
return await this.repository.updateById(id, args, transaction);
}

async getMerchantMonitoringMetrics({
projectIds,
features,
from,
to,
}: {
projectIds: string[];
features: TCustomerWithFeatures['features'];
from: string | undefined;
to: string | undefined;
}): Promise<{
totalActiveMerchants: number;
addedMerchantsCount: number;
unmonitoredMerchants: number;
}> {
// Metrics are currently mostly requested by month
if (!from) {
from = dayjs().startOf('month').toISOString();
}

if (!to) {
to = dayjs(from).add(1, 'month').toISOString();
}
r4zendev marked this conversation as resolved.
Show resolved Hide resolved
r4zendev marked this conversation as resolved.
Show resolved Hide resolved

const allProjectMerchants = await this.repository.findMany({}, projectIds);

const totalActiveMerchants = allProjectMerchants.filter(b => {
const disabledAt = z
.number()
.nullable()
.catch(() => null)
.parse(
(
b.metadata as {
featureConfig: Record<
(typeof FEATURE_LIST)[keyof typeof FEATURE_LIST],
TCustomerFeaturesConfig & { disabledAt: number | null | undefined }
>;
}
)?.featureConfig?.[FEATURE_LIST.ONGOING_MERCHANT_REPORT]?.disabledAt,
);

return (
disabledAt === null ||
(b.metadata === null && features?.ONGOING_MERCHANT_REPORT?.options?.runByDefault)
);
r4zendev marked this conversation as resolved.
Show resolved Hide resolved
}).length;

const addedMerchantsCount = await this.repository.count(
{
where: {
OR: [
{
metadata: {
path: ['featureConfig', FEATURE_LIST.ONGOING_MERCHANT_REPORT, 'disabledAt'],
r4zendev marked this conversation as resolved.
Show resolved Hide resolved
equals: Prisma.AnyNull,
},
},
features?.ONGOING_MERCHANT_REPORT?.options?.runByDefault
? { metadata: { equals: Prisma.AnyNull } }
: {},
],
createdAt: {
gte: dayjs(from).toISOString(),
lt: dayjs(to).toISOString(),
},
},
},
projectIds,
);

const unmonitoredMerchants = await this.repository.count(
{
where: {
OR: [
{
metadata: {
path: ['featureConfig', FEATURE_LIST.ONGOING_MERCHANT_REPORT, 'disabledAt'],
r4zendev marked this conversation as resolved.
Show resolved Hide resolved
not: 'null',
gte: dayjs(from).toDate().getTime(),
lt: dayjs(to).toDate().getTime(),
},
},
!features?.ONGOING_MERCHANT_REPORT?.options?.runByDefault
? { metadata: { equals: Prisma.AnyNull } }
: {},
],
},
},
projectIds,
);

return {
totalActiveMerchants,
addedMerchantsCount,
unmonitoredMerchants,
};
}

async fetchCompanyInformation({
registrationNumber,
jurisdictionCode,
Expand Down
Loading