Let automations fire on more CRM events and open the studio from the main nav.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { AutomationsModule } from '../automations/automations.module';
|
||||
import { InvoicesController } from './invoices.controller';
|
||||
import { InvoicesService } from './invoices.service';
|
||||
|
||||
@Module({
|
||||
imports: [AutomationsModule],
|
||||
controllers: [InvoicesController],
|
||||
providers: [InvoicesService],
|
||||
exports: [InvoicesService],
|
||||
|
||||
@@ -16,6 +16,7 @@ import type {
|
||||
import { Prisma } from '@prisma/client';
|
||||
import { PrismaService } from '../prisma/prisma.service';
|
||||
import { type Actor, ownerWhere } from '../common/record-scope';
|
||||
import { AutomationsService } from '../automations/automations.service';
|
||||
|
||||
type InvoiceActor = Pick<Actor, 'userId' | 'role'>;
|
||||
|
||||
@@ -37,7 +38,10 @@ type InvoiceRow = Prisma.InvoiceGetPayload<{ include: typeof include }>;
|
||||
|
||||
@Injectable()
|
||||
export class InvoicesService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
constructor(
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly automations: AutomationsService,
|
||||
) {}
|
||||
|
||||
async list(
|
||||
organizationId: string,
|
||||
@@ -264,7 +268,11 @@ export class InvoicesService {
|
||||
},
|
||||
include,
|
||||
});
|
||||
return this.toDto(row);
|
||||
const created = this.toDto(row);
|
||||
if (created.status !== 'draft' && created.status !== 'canceled') {
|
||||
await this.fireIssued(organizationId, created);
|
||||
}
|
||||
return created;
|
||||
}
|
||||
|
||||
async update(
|
||||
@@ -374,7 +382,15 @@ export class InvoicesService {
|
||||
await this.recomputeStatus(id);
|
||||
}
|
||||
|
||||
return this.get(organizationId, id, actor);
|
||||
const row = await this.get(organizationId, id, actor);
|
||||
const leftDraft =
|
||||
existing.status === 'draft' &&
|
||||
row.status !== 'draft' &&
|
||||
row.status !== 'canceled';
|
||||
if (leftDraft) {
|
||||
await this.fireIssued(organizationId, row);
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
async remove(
|
||||
@@ -443,7 +459,21 @@ export class InvoicesService {
|
||||
});
|
||||
|
||||
await this.recomputeStatus(invoiceId);
|
||||
return this.get(organizationId, invoiceId, actor);
|
||||
const row = await this.get(organizationId, invoiceId, actor);
|
||||
if (invoice.status === 'draft') {
|
||||
await this.fireIssued(organizationId, row);
|
||||
}
|
||||
await this.automations.runTrigger('invoice_paid', {
|
||||
organizationId,
|
||||
entityType: 'invoice',
|
||||
entityId: row.id,
|
||||
title: row.title || row.number,
|
||||
personId: row.person?.id ?? null,
|
||||
companyId: row.company?.id ?? null,
|
||||
dealId: row.deal?.id ?? null,
|
||||
ownerId: row.owner?.id ?? null,
|
||||
});
|
||||
return row;
|
||||
}
|
||||
|
||||
async removePayment(
|
||||
@@ -549,6 +579,19 @@ export class InvoicesService {
|
||||
return `FA-${String(count + 1).padStart(4, '0')}`;
|
||||
}
|
||||
|
||||
private async fireIssued(organizationId: string, row: InvoiceDto) {
|
||||
await this.automations.runTrigger('invoice_issued', {
|
||||
organizationId,
|
||||
entityType: 'invoice',
|
||||
entityId: row.id,
|
||||
title: row.title || row.number,
|
||||
personId: row.person?.id ?? null,
|
||||
companyId: row.company?.id ?? null,
|
||||
dealId: row.deal?.id ?? null,
|
||||
ownerId: row.owner?.id ?? null,
|
||||
});
|
||||
}
|
||||
|
||||
private async ensureExists(
|
||||
organizationId: string,
|
||||
id: string,
|
||||
|
||||
Reference in New Issue
Block a user