mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-15 04:10:32 +00:00
fix: invoice generate sharable link
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import { Knex } from 'knex';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { CommandItemCategoryValidatorService } from './CommandItemCategoryValidator.service';
|
||||
import { ItemCategory } from '../models/ItemCategory.model';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Knex } from 'knex';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { events } from '@/common/events/events';
|
||||
import { IItemCategoryDeletedPayload } from '../ItemCategory.interfaces';
|
||||
import { Item } from '@/modules/Items/models/Item';
|
||||
@@ -46,7 +46,10 @@ export class DeleteItemCategoryService {
|
||||
await this.unassociateItemsWithCategories(itemCategoryId, trx);
|
||||
|
||||
// Delete item category.
|
||||
await ItemCategory.query(trx).findById(itemCategoryId).delete();
|
||||
await this.itemCategoryModel()
|
||||
.query(trx)
|
||||
.findById(itemCategoryId)
|
||||
.delete();
|
||||
|
||||
// Triggers `onItemCategoryDeleted` event.
|
||||
await this.eventEmitter.emitAsync(events.itemCategory.onDeleted, {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import * as moment from 'moment';
|
||||
import { ClsService } from 'nestjs-cls';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { TenantModelProxy } from '../System/models/TenantBaseModel';
|
||||
import { SaleInvoice } from '../SaleInvoices/models/SaleInvoice';
|
||||
@@ -6,8 +7,6 @@ import { TransformerInjectable } from '../Transformer/TransformerInjectable.serv
|
||||
import { PaymentLink } from './models/PaymentLink';
|
||||
import { ServiceError } from '../Items/ServiceError';
|
||||
import { GetInvoicePaymentLinkMetaTransformer } from '../SaleInvoices/queries/GetInvoicePaymentLink.transformer';
|
||||
import { ClsService } from 'nestjs-cls';
|
||||
import { TenancyContext } from '../Tenancy/TenancyContext.service';
|
||||
import { TenantModel } from '../System/models/TenantModel';
|
||||
|
||||
@Injectable()
|
||||
@@ -15,7 +14,6 @@ export class GetInvoicePaymentLinkMetadata {
|
||||
constructor(
|
||||
private readonly transformer: TransformerInjectable,
|
||||
private readonly clsService: ClsService,
|
||||
private readonly tenancyContext: TenancyContext,
|
||||
|
||||
@Inject(SaleInvoice.name)
|
||||
private readonly saleInvoiceModel: TenantModelProxy<typeof SaleInvoice>,
|
||||
|
||||
@@ -25,10 +25,7 @@ export class PaymentLinksController {
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
data: {
|
||||
type: 'object',
|
||||
description: 'Payment link metadata',
|
||||
},
|
||||
data: { type: 'object', description: 'Payment link metadata' },
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
CreateSaleInvoiceDto,
|
||||
EditSaleInvoiceDto,
|
||||
} from './dtos/SaleInvoice.dto';
|
||||
import { GenerateShareLink } from './commands/GenerateInvoicePaymentLink.service';
|
||||
|
||||
@Injectable()
|
||||
export class SaleInvoiceApplication {
|
||||
@@ -39,6 +40,7 @@ export class SaleInvoiceApplication {
|
||||
private getSaleInvoiceStateService: GetSaleInvoiceState,
|
||||
private sendSaleInvoiceMailService: SendSaleInvoiceMail,
|
||||
private getSaleInvoiceMailStateService: GetSaleInvoiceMailState,
|
||||
private generateShareLinkService: GenerateShareLink,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -202,4 +204,23 @@ export class SaleInvoiceApplication {
|
||||
saleInvoiceid,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the given sale invoice sharable link.
|
||||
* @param {number} saleInvoiceId
|
||||
* @param {string} publicity
|
||||
* @param {string} expiryTime
|
||||
* @returns
|
||||
*/
|
||||
public generateSaleInvoiceSharableLink(
|
||||
saleInvoiceId: number,
|
||||
publicity: string = 'private',
|
||||
expiryTime: string = '',
|
||||
) {
|
||||
return this.generateShareLinkService.generatePaymentLink(
|
||||
saleInvoiceId,
|
||||
publicity,
|
||||
expiryTime,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,12 +38,14 @@ import { AcceptType } from '@/constants/accept-type';
|
||||
import { SaleInvoiceResponseDto } from './dtos/SaleInvoiceResponse.dto';
|
||||
import { PaginatedResponseDto } from '@/common/dtos/PaginatedResults.dto';
|
||||
import { SaleInvoiceStateResponseDto } from './dtos/SaleInvoiceState.dto';
|
||||
import { GenerateSaleInvoiceSharableLinkResponseDto } from './dtos/generateSaleInvoiceSharableLinkResponse.dto';
|
||||
|
||||
@Controller('sale-invoices')
|
||||
@ApiTags('Sale Invoices')
|
||||
@ApiExtraModels(SaleInvoiceResponseDto)
|
||||
@ApiExtraModels(PaginatedResponseDto)
|
||||
@ApiExtraModels(SaleInvoiceStateResponseDto)
|
||||
@ApiExtraModels(GenerateSaleInvoiceSharableLinkResponseDto)
|
||||
@ApiHeader({
|
||||
name: 'organization-id',
|
||||
description: 'The organization id',
|
||||
@@ -318,4 +320,25 @@ export class SaleInvoicesController {
|
||||
): Promise<SaleInvoiceMailState> {
|
||||
return this.saleInvoiceApplication.getSaleInvoiceMailState(id);
|
||||
}
|
||||
|
||||
@Post(':id/generate-link')
|
||||
@ApiOperation({
|
||||
summary: 'Generate sharable sale invoice link (private or public)',
|
||||
})
|
||||
@ApiResponse({
|
||||
status: 201,
|
||||
description: 'The link has been generated successfully.',
|
||||
schema: {
|
||||
$ref: getSchemaPath(GenerateSaleInvoiceSharableLinkResponseDto),
|
||||
},
|
||||
})
|
||||
@ApiParam({
|
||||
name: 'id',
|
||||
required: true,
|
||||
type: Number,
|
||||
description: 'The sale invoice id',
|
||||
})
|
||||
generateSaleInvoiceSharableLink(@Param('id', ParseIntPipe) id: number) {
|
||||
return this.saleInvoiceApplication.generateSaleInvoiceSharableLink(id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import { events } from '@/common/events/events';
|
||||
import { PaymentLink } from '@/modules/PaymentLinks/models/PaymentLink';
|
||||
import { SaleInvoice } from '../models/SaleInvoice';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
|
||||
|
||||
@Injectable()
|
||||
export class GenerateShareLink {
|
||||
@@ -16,12 +17,13 @@ export class GenerateShareLink {
|
||||
private uow: UnitOfWork,
|
||||
private eventPublisher: EventEmitter2,
|
||||
private transformer: TransformerInjectable,
|
||||
private tenancyContext: TenancyContext,
|
||||
|
||||
@Inject(SaleInvoice.name)
|
||||
private saleInvoiceModel: TenantModelProxy<typeof SaleInvoice>,
|
||||
|
||||
@Inject(PaymentLink.name)
|
||||
private paymentLinkModel: TenantModelProxy<typeof PaymentLink>,
|
||||
private paymentLinkModel: typeof PaymentLink,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -39,10 +41,10 @@ export class GenerateShareLink {
|
||||
.query()
|
||||
.findById(saleInvoiceId)
|
||||
.throwIfNotFound();
|
||||
const tenant = await this.tenancyContext.getTenant();
|
||||
|
||||
// Generate unique uuid for sharable link.
|
||||
const linkId = uuidv4() as string;
|
||||
|
||||
const commonEventPayload = {
|
||||
saleInvoiceId,
|
||||
publicity,
|
||||
@@ -54,11 +56,12 @@ export class GenerateShareLink {
|
||||
events.saleInvoice.onPublicLinkGenerating,
|
||||
{ ...commonEventPayload, trx },
|
||||
);
|
||||
const paymentLink = await this.paymentLinkModel().query().insert({
|
||||
const paymentLink = await this.paymentLinkModel.query().insert({
|
||||
linkId,
|
||||
publicity,
|
||||
resourceId: foundInvoice.id,
|
||||
resourceType: 'SaleInvoice',
|
||||
tenantId: tenant.id,
|
||||
});
|
||||
// Triggers `onPublicSharableLinkGenerated` event.
|
||||
await this.eventPublisher.emitAsync(
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
export class GenerateSaleInvoiceSharableLinkResponseDto {
|
||||
@ApiProperty({
|
||||
description: 'Sharable payment link for the sale invoice',
|
||||
example:
|
||||
'http://localhost:3000/payment/123e4567-e89b-12d3-a456-426614174000',
|
||||
})
|
||||
link: string;
|
||||
}
|
||||
@@ -29,7 +29,6 @@ import { SaleInvoice } from '@/modules/SaleInvoices/models/SaleInvoice';
|
||||
import { PaymentReceivedEntry } from '@/modules/PaymentReceived/models/PaymentReceivedEntry';
|
||||
import { CreditNoteAppliedInvoice } from '@/modules/CreditNotesApplyInvoice/models/CreditNoteAppliedInvoice';
|
||||
import { CreditNote } from '@/modules/CreditNotes/models/CreditNote';
|
||||
import { PaymentLink } from '@/modules/PaymentLinks/models/PaymentLink';
|
||||
import { SaleReceipt } from '@/modules/SaleReceipts/models/SaleReceipt';
|
||||
import { ManualJournal } from '@/modules/ManualJournals/models/ManualJournal';
|
||||
import { ManualJournalEntry } from '@/modules/ManualJournals/models/ManualJournalEntry';
|
||||
@@ -70,7 +69,6 @@ const models = [
|
||||
CreditNoteAppliedInvoice,
|
||||
CreditNote,
|
||||
RefundCreditNote,
|
||||
PaymentLink,
|
||||
SaleReceipt,
|
||||
ManualJournal,
|
||||
ManualJournalEntry,
|
||||
@@ -82,7 +80,6 @@ const models = [
|
||||
TenantUser,
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Decorator factory that registers a model with the tenancy system.
|
||||
* @param model The model class to register
|
||||
|
||||
@@ -49,7 +49,7 @@ export const SharePaymentLinkForm = ({
|
||||
generateShareLink(values)
|
||||
.then((res) => {
|
||||
setSubmitting(false);
|
||||
setUrl(res.link?.link);
|
||||
setUrl(res.link);
|
||||
})
|
||||
.catch(() => {
|
||||
setSubmitting(false);
|
||||
|
||||
@@ -45,7 +45,10 @@ export function useCreatePaymentLink(
|
||||
return useMutation<CreatePaymentLinkResponse, Error, CreatePaymentLinkValues>(
|
||||
(values) =>
|
||||
apiRequest
|
||||
.post('/payment-links/generate', transfromToSnakeCase(values))
|
||||
.post(
|
||||
`/sale-invoices/${values.transactionId}/generate-link`,
|
||||
transfromToSnakeCase(values),
|
||||
)
|
||||
.then((res) => res.data),
|
||||
{
|
||||
...options,
|
||||
|
||||
Reference in New Issue
Block a user