mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-21 15:20:34 +00:00
fix: retrieve the build org job state
This commit is contained in:
@@ -2,7 +2,6 @@ import { Inject, Injectable } from '@nestjs/common';
|
|||||||
import { ERRORS } from '../Bills.constants';
|
import { ERRORS } from '../Bills.constants';
|
||||||
import { Bill } from '../models/Bill';
|
import { Bill } from '../models/Bill';
|
||||||
import { ServiceError } from '@/modules/Items/ServiceError';
|
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||||
import { IItemEntryDTO } from '@/modules/TransactionItemEntry/ItemEntry.types';
|
|
||||||
import { Item } from '@/modules/Items/models/Item';
|
import { Item } from '@/modules/Items/models/Item';
|
||||||
import { BillPaymentEntry } from '@/modules/BillPayments/models/BillPaymentEntry';
|
import { BillPaymentEntry } from '@/modules/BillPayments/models/BillPaymentEntry';
|
||||||
import { BillLandedCost } from '@/modules/BillLandedCosts/models/BillLandedCost';
|
import { BillLandedCost } from '@/modules/BillLandedCosts/models/BillLandedCost';
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
import { ApiTags, ApiOperation, ApiResponse, ApiBody } from '@nestjs/swagger';
|
import {
|
||||||
|
ApiTags,
|
||||||
|
ApiOperation,
|
||||||
|
ApiResponse,
|
||||||
|
ApiBody,
|
||||||
|
ApiOkResponse,
|
||||||
|
} from '@nestjs/swagger';
|
||||||
import {
|
import {
|
||||||
Controller,
|
Controller,
|
||||||
Post,
|
Post,
|
||||||
@@ -9,6 +15,7 @@ import {
|
|||||||
Res,
|
Res,
|
||||||
Next,
|
Next,
|
||||||
HttpCode,
|
HttpCode,
|
||||||
|
Param,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { Request, Response, NextFunction } from 'express';
|
import { Request, Response, NextFunction } from 'express';
|
||||||
import { BuildOrganizationService } from './commands/BuildOrganization.service';
|
import { BuildOrganizationService } from './commands/BuildOrganization.service';
|
||||||
@@ -20,6 +27,7 @@ import { GetCurrentOrganizationService } from './queries/GetCurrentOrganization.
|
|||||||
import { UpdateOrganizationService } from './commands/UpdateOrganization.service';
|
import { UpdateOrganizationService } from './commands/UpdateOrganization.service';
|
||||||
import { IgnoreTenantInitializedRoute } from '../Tenancy/EnsureTenantIsInitialized.guard';
|
import { IgnoreTenantInitializedRoute } from '../Tenancy/EnsureTenantIsInitialized.guard';
|
||||||
import { IgnoreTenantSeededRoute } from '../Tenancy/EnsureTenantIsSeeded.guards';
|
import { IgnoreTenantSeededRoute } from '../Tenancy/EnsureTenantIsSeeded.guards';
|
||||||
|
import { GetBuildOrganizationBuildJob } from './commands/GetBuildOrganizationJob.service';
|
||||||
|
|
||||||
@ApiTags('Organization')
|
@ApiTags('Organization')
|
||||||
@Controller('organization')
|
@Controller('organization')
|
||||||
@@ -30,6 +38,7 @@ export class OrganizationController {
|
|||||||
private readonly buildOrganizationService: BuildOrganizationService,
|
private readonly buildOrganizationService: BuildOrganizationService,
|
||||||
private readonly getCurrentOrgService: GetCurrentOrganizationService,
|
private readonly getCurrentOrgService: GetCurrentOrganizationService,
|
||||||
private readonly updateOrganizationService: UpdateOrganizationService,
|
private readonly updateOrganizationService: UpdateOrganizationService,
|
||||||
|
private readonly getBuildOrganizationJobService: GetBuildOrganizationBuildJob,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@Post('build')
|
@Post('build')
|
||||||
@@ -51,6 +60,13 @@ export class OrganizationController {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Get('build/:buildJobId')
|
||||||
|
@HttpCode(200)
|
||||||
|
@ApiOperation({ summary: 'Gets the organization build job details' })
|
||||||
|
async buildJob(@Param('buildJobId') buildJobId: string) {
|
||||||
|
return this.getBuildOrganizationJobService.getJobDetails(buildJobId);
|
||||||
|
}
|
||||||
|
|
||||||
@Get('current')
|
@Get('current')
|
||||||
@HttpCode(200)
|
@HttpCode(200)
|
||||||
@ApiOperation({ summary: 'Get current organization' })
|
@ApiOperation({ summary: 'Get current organization' })
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { TenantDBManagerModule } from '../TenantDBManager/TenantDBManager.module
|
|||||||
import { OrganizationBaseCurrencyLocking } from './Organization/OrganizationBaseCurrencyLocking.service';
|
import { OrganizationBaseCurrencyLocking } from './Organization/OrganizationBaseCurrencyLocking.service';
|
||||||
import { SyncSystemUserToTenantService } from './commands/SyncSystemUserToTenant.service';
|
import { SyncSystemUserToTenantService } from './commands/SyncSystemUserToTenant.service';
|
||||||
import { SyncSystemUserToTenantSubscriber } from './subscribers/SyncSystemUserToTenant.subscriber';
|
import { SyncSystemUserToTenantSubscriber } from './subscribers/SyncSystemUserToTenant.subscriber';
|
||||||
|
import { GetBuildOrganizationBuildJob } from './commands/GetBuildOrganizationJob.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
providers: [
|
providers: [
|
||||||
@@ -23,7 +24,8 @@ import { SyncSystemUserToTenantSubscriber } from './subscribers/SyncSystemUserTo
|
|||||||
CommandOrganizationValidators,
|
CommandOrganizationValidators,
|
||||||
OrganizationBaseCurrencyLocking,
|
OrganizationBaseCurrencyLocking,
|
||||||
SyncSystemUserToTenantService,
|
SyncSystemUserToTenantService,
|
||||||
SyncSystemUserToTenantSubscriber
|
SyncSystemUserToTenantSubscriber,
|
||||||
|
GetBuildOrganizationBuildJob
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BullModule.registerQueue({ name: OrganizationBuildQueue }),
|
BullModule.registerQueue({ name: OrganizationBuildQueue }),
|
||||||
|
|||||||
@@ -58,3 +58,9 @@ export const OrganizationBuildQueueJob = 'OrganizationBuildQueueJob';
|
|||||||
export interface OrganizationBuildQueueJobPayload extends TenantJobPayload {
|
export interface OrganizationBuildQueueJobPayload extends TenantJobPayload {
|
||||||
buildDto: BuildOrganizationDto;
|
buildDto: BuildOrganizationDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface BuildOrganizationResult {
|
||||||
|
delay: number;
|
||||||
|
processedOn: number;
|
||||||
|
jobId: string;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import { Queue } from 'bullmq';
|
import { Queue } from 'bullmq';
|
||||||
import { InjectQueue } from '@nestjs/bullmq';
|
import { InjectQueue } from '@nestjs/bullmq';
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
import {
|
import {
|
||||||
|
BuildOrganizationResult,
|
||||||
IOrganizationBuildEventPayload,
|
IOrganizationBuildEventPayload,
|
||||||
IOrganizationBuiltEventPayload,
|
IOrganizationBuiltEventPayload,
|
||||||
OrganizationBuildQueue,
|
OrganizationBuildQueue,
|
||||||
OrganizationBuildQueueJob,
|
OrganizationBuildQueueJob,
|
||||||
OrganizationBuildQueueJobPayload,
|
OrganizationBuildQueueJobPayload,
|
||||||
} from '../Organization.types';
|
} from '../Organization.types';
|
||||||
import { Injectable } from '@nestjs/common';
|
|
||||||
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
|
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
|
||||||
import {
|
import {
|
||||||
throwIfTenantInitizalized,
|
throwIfTenantInitizalized,
|
||||||
@@ -48,7 +49,7 @@ export class BuildOrganizationService {
|
|||||||
await this.tenantsManager.createDatabase();
|
await this.tenantsManager.createDatabase();
|
||||||
|
|
||||||
await this.tenantsManager.migrateTenant();
|
await this.tenantsManager.migrateTenant();
|
||||||
await this.tenantsManager.seedTenant()
|
await this.tenantsManager.seedTenant();
|
||||||
|
|
||||||
// Throws `onOrganizationBuild` event.
|
// Throws `onOrganizationBuild` event.
|
||||||
await this.eventPublisher.emitAsync(events.organization.build, {
|
await this.eventPublisher.emitAsync(events.organization.build, {
|
||||||
@@ -77,7 +78,7 @@ export class BuildOrganizationService {
|
|||||||
*/
|
*/
|
||||||
async buildRunJob(
|
async buildRunJob(
|
||||||
buildDTO: BuildOrganizationDto,
|
buildDTO: BuildOrganizationDto,
|
||||||
): Promise<{ nextRunAt: Date; jobId: string }> {
|
): Promise<BuildOrganizationResult> {
|
||||||
const tenant = await this.tenancyContext.getTenant();
|
const tenant = await this.tenancyContext.getTenant();
|
||||||
const systemUser = await this.tenancyContext.getSystemUser();
|
const systemUser = await this.tenancyContext.getSystemUser();
|
||||||
|
|
||||||
@@ -106,8 +107,9 @@ export class BuildOrganizationService {
|
|||||||
await this.tenantRepository.markAsBuilding(jobMeta.id).findById(tenant.id);
|
await this.tenantRepository.markAsBuilding(jobMeta.id).findById(tenant.id);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
nextRunAt: jobMeta.data.nextRunAt,
|
delay: jobMeta.delay,
|
||||||
jobId: jobMeta.data.id,
|
processedOn: jobMeta.processedOn,
|
||||||
|
jobId: jobMeta.id,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import { Queue } from 'bullmq';
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { InjectQueue } from '@nestjs/bullmq';
|
||||||
|
import { OrganizationBuildQueue } from '../Organization.types';
|
||||||
|
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class GetBuildOrganizationBuildJob {
|
||||||
|
constructor(
|
||||||
|
@InjectQueue(OrganizationBuildQueue)
|
||||||
|
private readonly organizationBuildQueue: Queue,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the build job details by job ID.
|
||||||
|
* @param {string} jobId - The ID of the job to retrieve.
|
||||||
|
* @returns {Promise<any>} - Returns the job details.
|
||||||
|
*/
|
||||||
|
async getJobDetails(jobId: string): Promise<any> {
|
||||||
|
const job = await this.organizationBuildQueue.getJob(jobId);
|
||||||
|
|
||||||
|
if (!job) {
|
||||||
|
throw new ServiceError('Job not found', 'JOB.NOT_FOUND');
|
||||||
|
}
|
||||||
|
const state = await job.getState();
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: job.id,
|
||||||
|
state,
|
||||||
|
progress: job.progress,
|
||||||
|
isCompleted: state === 'completed',
|
||||||
|
isRunning: state === 'active',
|
||||||
|
isWaiting: state === 'waiting' || state === 'waiting-children',
|
||||||
|
isFailed: state === 'failed',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,7 +25,7 @@ function SetupInitializingForm({
|
|||||||
const [isJobDone, setIsJobDone] = React.useState(false);
|
const [isJobDone, setIsJobDone] = React.useState(false);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: { running, queued, failed, completed },
|
data: { isRunning, isWaiting, isFailed, isCompleted },
|
||||||
isFetching: isJobFetching,
|
isFetching: isJobFetching,
|
||||||
} = useJob(organization?.build_job_id, {
|
} = useJob(organization?.build_job_id, {
|
||||||
refetchInterval: 2000,
|
refetchInterval: 2000,
|
||||||
@@ -33,11 +33,11 @@ function SetupInitializingForm({
|
|||||||
});
|
});
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (completed) {
|
if (isCompleted) {
|
||||||
refetch();
|
refetch();
|
||||||
setIsJobDone(true);
|
setIsJobDone(true);
|
||||||
}
|
}
|
||||||
}, [refetch, completed, setOrganizationSetupCompleted]);
|
}, [refetch, isCompleted, setOrganizationSetupCompleted]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (isSuccess && isJobDone) {
|
if (isSuccess && isJobDone) {
|
||||||
@@ -48,11 +48,11 @@ function SetupInitializingForm({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="setup-initializing-form">
|
<div class="setup-initializing-form">
|
||||||
{failed ? (
|
{isFailed ? (
|
||||||
<SetupInitializingFailed />
|
<SetupInitializingFailed />
|
||||||
) : running || queued || isJobFetching ? (
|
) : isRunning || isWaiting || isJobFetching ? (
|
||||||
<SetupInitializingRunning />
|
<SetupInitializingRunning />
|
||||||
) : completed ? (
|
) : isCompleted ? (
|
||||||
<SetupInitializingCompleted />
|
<SetupInitializingCompleted />
|
||||||
) : (
|
) : (
|
||||||
<SetupInitializingFailed />
|
<SetupInitializingFailed />
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
|
import { transformToCamelCase } from '@/utils';
|
||||||
import { useRequestQuery } from '../useQueryRequest';
|
import { useRequestQuery } from '../useQueryRequest';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -7,9 +8,9 @@ import { useRequestQuery } from '../useQueryRequest';
|
|||||||
export function useJob(jobId, props = {}) {
|
export function useJob(jobId, props = {}) {
|
||||||
return useRequestQuery(
|
return useRequestQuery(
|
||||||
['JOB', jobId],
|
['JOB', jobId],
|
||||||
{ method: 'get', url: `jobs/${jobId}` },
|
{ method: 'get', url: `organization/build/${jobId}` },
|
||||||
{
|
{
|
||||||
select: (res) => res.data.job,
|
select: (res) => transformToCamelCase(res.data),
|
||||||
defaultData: {},
|
defaultData: {},
|
||||||
...props,
|
...props,
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user