mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-17 21:30:31 +00:00
refactor: nestjs
This commit is contained in:
@@ -20,6 +20,16 @@ import { IFilterMeta } from '@/interfaces/Model';
|
||||
|
||||
@Injectable()
|
||||
export class AccountsApplication {
|
||||
/**
|
||||
* @param {CreateAccountService} createAccountService - The create account service.
|
||||
* @param {EditAccount} editAccountService - The edit account service.
|
||||
* @param {DeleteAccount} deleteAccountService - The delete account service.
|
||||
* @param {ActivateAccount} activateAccountService - The activate account service.
|
||||
* @param {GetAccountTypesService} getAccountTypesService - The get account types service.
|
||||
* @param {GetAccount} getAccountService - The get account service.
|
||||
* @param {GetAccountTransactionsService} getAccountTransactionsService - The get account transactions service.
|
||||
* @param {GetAccountsService} getAccountsService - The get accounts service.
|
||||
*/
|
||||
constructor(
|
||||
private readonly createAccountService: CreateAccountService,
|
||||
private readonly editAccountService: EditAccount,
|
||||
|
||||
@@ -10,6 +10,12 @@ import { TenantModelProxy } from '../System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class ActivateAccount {
|
||||
/**
|
||||
* @param {EventEmitter2} eventEmitter - The event emitter.
|
||||
* @param {UnitOfWork} uow - The unit of work.
|
||||
* @param {AccountRepository} accountRepository - The account repository.
|
||||
* @param {TenantModelProxy<typeof Account>} accountModel - The account model.
|
||||
*/
|
||||
constructor(
|
||||
private readonly eventEmitter: EventEmitter2,
|
||||
private readonly uow: UnitOfWork,
|
||||
@@ -21,8 +27,8 @@ export class ActivateAccount {
|
||||
|
||||
/**
|
||||
* Activates/Inactivates the given account.
|
||||
* @param {number} accountId
|
||||
* @param {boolean} activate
|
||||
* @param {number} accountId - The account id.
|
||||
* @param {boolean} activate - Activate or inactivate the account.
|
||||
*/
|
||||
public activateAccount = async (accountId: number, activate?: boolean) => {
|
||||
// Retrieve the given account or throw not found error.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import {
|
||||
IsString,
|
||||
IsOptional,
|
||||
@@ -11,41 +12,92 @@ export class CreateAccountDTO {
|
||||
@IsString()
|
||||
@MinLength(3)
|
||||
@MaxLength(255) // Assuming DATATYPES_LENGTH.STRING is 255
|
||||
@ApiProperty({
|
||||
description: 'Account name',
|
||||
example: 'Cash Account',
|
||||
minLength: 3,
|
||||
maxLength: 255,
|
||||
})
|
||||
name: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@MinLength(3)
|
||||
@MaxLength(6)
|
||||
@ApiProperty({
|
||||
description: 'Account code',
|
||||
example: 'CA001',
|
||||
required: false,
|
||||
minLength: 3,
|
||||
maxLength: 6,
|
||||
})
|
||||
code?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@ApiProperty({
|
||||
description: 'Currency code for the account',
|
||||
example: 'USD',
|
||||
required: false,
|
||||
})
|
||||
currencyCode?: string;
|
||||
|
||||
@IsString()
|
||||
@MinLength(3)
|
||||
@MaxLength(255)
|
||||
@ApiProperty({
|
||||
description: 'Type of account',
|
||||
example: 'asset',
|
||||
minLength: 3,
|
||||
maxLength: 255,
|
||||
})
|
||||
accountType: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@MaxLength(65535)
|
||||
@ApiProperty({
|
||||
description: 'Account description',
|
||||
example: 'Main cash account for daily operations',
|
||||
required: false,
|
||||
maxLength: 65535,
|
||||
})
|
||||
description?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@ApiProperty({
|
||||
description: 'ID of the parent account',
|
||||
example: 1,
|
||||
required: false,
|
||||
})
|
||||
parentAccountId?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
@ApiProperty({
|
||||
description: 'Whether the account is active',
|
||||
example: true,
|
||||
required: false,
|
||||
default: true,
|
||||
})
|
||||
active?: boolean;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@ApiProperty({
|
||||
description: 'Plaid account ID for syncing',
|
||||
example: 'plaid_account_123456',
|
||||
required: false,
|
||||
})
|
||||
plaidAccountId?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@ApiProperty({
|
||||
description: 'Plaid item ID for syncing',
|
||||
example: 'plaid_item_123456',
|
||||
required: false,
|
||||
})
|
||||
plaidItemId?: string;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import {
|
||||
IsString,
|
||||
IsOptional,
|
||||
@@ -9,26 +10,45 @@ import {
|
||||
export class EditAccountDTO {
|
||||
@IsString()
|
||||
@MinLength(3)
|
||||
@MaxLength(255) // Assuming DATATYPES_LENGTH.STRING is 255
|
||||
@MaxLength(255)
|
||||
@ApiProperty({
|
||||
description: 'The name of the account',
|
||||
example: 'Bank Account',
|
||||
})
|
||||
name: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@MinLength(3)
|
||||
@MaxLength(6)
|
||||
@ApiProperty({
|
||||
description: 'The code of the account',
|
||||
example: '123456',
|
||||
})
|
||||
code?: string;
|
||||
|
||||
@IsString()
|
||||
@MinLength(3)
|
||||
@MaxLength(255) // Assuming DATATYPES_LENGTH.STRING is 255
|
||||
@MaxLength(255)
|
||||
@ApiProperty({
|
||||
description: 'The type of the account',
|
||||
example: 'Bank Account',
|
||||
})
|
||||
accountType: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@MaxLength(65535) // Assuming DATATYPES_LENGTH.TEXT is 65535
|
||||
@ApiProperty({
|
||||
description: 'The description of the account',
|
||||
example: 'This is a description',
|
||||
})
|
||||
description?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@ApiProperty({
|
||||
description: 'The parent account ID of the account',
|
||||
example: 1,
|
||||
})
|
||||
parentAccountId?: number;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
IsNotEmpty,
|
||||
} from 'class-validator';
|
||||
import { BankRuleComparator } from '../types';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
class BankRuleConditionDto {
|
||||
@IsNotEmpty()
|
||||
@@ -37,43 +38,83 @@ class BankRuleConditionDto {
|
||||
export class CommandBankRuleDto {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@ApiProperty({
|
||||
description: 'The name of the bank rule',
|
||||
example: 'Monthly Salary',
|
||||
})
|
||||
name: string;
|
||||
|
||||
@IsInt()
|
||||
@Min(0)
|
||||
@ApiProperty({
|
||||
description: 'The order of the bank rule',
|
||||
example: 1,
|
||||
})
|
||||
order: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@Min(0)
|
||||
@ApiProperty({
|
||||
description: 'The account ID to apply the rule if',
|
||||
example: 1,
|
||||
})
|
||||
applyIfAccountId?: number;
|
||||
|
||||
@IsIn(['deposit', 'withdrawal'])
|
||||
@ApiProperty({
|
||||
description: 'The transaction type to apply the rule if',
|
||||
example: 'deposit',
|
||||
})
|
||||
applyIfTransactionType: 'deposit' | 'withdrawal';
|
||||
|
||||
@IsString()
|
||||
@IsIn(['and', 'or'])
|
||||
@ApiProperty({
|
||||
description: 'The conditions type to apply the rule if',
|
||||
example: 'and',
|
||||
})
|
||||
conditionsType: 'and' | 'or' = 'and';
|
||||
|
||||
@IsArray()
|
||||
@ArrayMinSize(1)
|
||||
@ValidateNested({ each: true })
|
||||
@Type(() => BankRuleConditionDto)
|
||||
@ApiProperty({
|
||||
description: 'The conditions to apply the rule if',
|
||||
example: [{ field: 'description', comparator: 'contains', value: 'Salary' }],
|
||||
})
|
||||
conditions: BankRuleConditionDto[];
|
||||
|
||||
@IsString()
|
||||
@ApiProperty({
|
||||
description: 'The category to assign the rule if',
|
||||
example: 'Income:Salary',
|
||||
})
|
||||
assignCategory: string;
|
||||
|
||||
@IsInt()
|
||||
@Min(0)
|
||||
@ApiProperty({
|
||||
description: 'The account ID to assign the rule if',
|
||||
example: 1,
|
||||
})
|
||||
assignAccountId: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@ApiProperty({
|
||||
description: 'The payee to assign the rule if',
|
||||
example: 'Employer Inc.',
|
||||
})
|
||||
assignPayee?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@ApiProperty({
|
||||
description: 'The memo to assign the rule if',
|
||||
example: 'Monthly Salary',
|
||||
})
|
||||
assignMemo?: string;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ export class GetBankRuleService {
|
||||
|
||||
/**
|
||||
* Retrieves the bank rule.
|
||||
* @param {number} ruleId
|
||||
* @param {number} ruleId - Rule id.
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
async getBankRule(ruleId: number): Promise<any> {
|
||||
|
||||
@@ -6,14 +6,23 @@ import {
|
||||
ValidateNested,
|
||||
} from 'class-validator';
|
||||
import { Type } from 'class-transformer';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
export class MatchTransactionEntryDto {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@ApiProperty({
|
||||
description: 'The type of the reference',
|
||||
example: 'SaleInvoice',
|
||||
})
|
||||
referenceType: string;
|
||||
|
||||
@IsNumber()
|
||||
@IsNotEmpty()
|
||||
@ApiProperty({
|
||||
description: 'The ID of the reference',
|
||||
example: 1,
|
||||
})
|
||||
referenceId: number;
|
||||
}
|
||||
|
||||
@@ -21,5 +30,12 @@ export class MatchBankTransactionDto {
|
||||
@IsArray()
|
||||
@ValidateNested({ each: true })
|
||||
@Type(() => MatchTransactionEntryDto)
|
||||
@ApiProperty({
|
||||
description: 'The entries to match',
|
||||
example: [
|
||||
{ referenceType: 'SaleInvoice', referenceId: 1 },
|
||||
{ referenceType: 'SaleInvoice', referenceId: 2 },
|
||||
],
|
||||
})
|
||||
entries: MatchTransactionEntryDto[];
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,15 @@ import { CreateBranchDto, EditBranchDto } from './dtos/Branch.dto';
|
||||
|
||||
@Injectable()
|
||||
export class BranchesApplication {
|
||||
/**
|
||||
* @param {CreateBranchService} createBranchService - Create branch service.
|
||||
* @param {EditBranchService} editBranchService - Edit branch service.
|
||||
* @param {DeleteBranchService} deleteBranchService - Delete branch service.
|
||||
* @param {GetBranchService} getBranchService - Get branch service.
|
||||
* @param {GetBranchesService} getBranchesService - Get branches service.
|
||||
* @param {ActivateBranches} activateBranchesService - Activate branches service.
|
||||
* @param {MarkBranchAsPrimaryService} markBranchAsPrimaryService - Mark branch as primary service.
|
||||
*/
|
||||
constructor(
|
||||
private readonly createBranchService: CreateBranchService,
|
||||
private readonly editBranchService: EditBranchService,
|
||||
|
||||
@@ -9,48 +9,76 @@ import {
|
||||
} from 'class-validator';
|
||||
|
||||
class CommandBranchDto {
|
||||
@ApiProperty({ description: 'Branch name' })
|
||||
@ApiProperty({
|
||||
description: 'Branch name',
|
||||
example: 'Main Branch',
|
||||
})
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
name: string;
|
||||
|
||||
@ApiPropertyOptional({ description: 'Branch code' })
|
||||
@ApiPropertyOptional({
|
||||
description: 'Whether this is the primary branch',
|
||||
example: true,
|
||||
default: false,
|
||||
})
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
primary?: boolean;
|
||||
|
||||
@ApiPropertyOptional({ description: 'Branch code' })
|
||||
@ApiPropertyOptional({
|
||||
description: 'Branch code',
|
||||
example: 'BR001',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
code?: string;
|
||||
|
||||
@ApiPropertyOptional({ description: 'Branch address' })
|
||||
@ApiPropertyOptional({
|
||||
description: 'Branch address',
|
||||
example: '123 Main Street',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
address?: string;
|
||||
|
||||
@ApiPropertyOptional({ description: 'Branch city' })
|
||||
@ApiPropertyOptional({
|
||||
description: 'Branch city',
|
||||
example: 'New York',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
city?: string;
|
||||
|
||||
@ApiPropertyOptional({ description: 'Branch country' })
|
||||
@ApiPropertyOptional({
|
||||
description: 'Branch country',
|
||||
example: 'USA',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
country?: string;
|
||||
|
||||
@ApiPropertyOptional({ description: 'Branch phone number' })
|
||||
@ApiPropertyOptional({
|
||||
description: 'Branch phone number',
|
||||
example: '+1-555-123-4567',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
phone_number?: string;
|
||||
|
||||
@ApiPropertyOptional({ description: 'Branch email' })
|
||||
@ApiPropertyOptional({
|
||||
description: 'Branch email',
|
||||
example: 'branch@example.com',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsEmail()
|
||||
@IsString()
|
||||
email?: string;
|
||||
|
||||
@ApiPropertyOptional({ description: 'Branch website' })
|
||||
@ApiPropertyOptional({
|
||||
description: 'Branch website',
|
||||
example: 'https://www.example.com/branch',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsUrl()
|
||||
@IsString()
|
||||
|
||||
@@ -17,7 +17,7 @@ import { BrandingTemplateDTOTransformer } from '../../PdfTemplate/BrandingTempla
|
||||
import { assocItemEntriesDefaultIndex } from '@/utils/associate-item-entries-index';
|
||||
import { CreditNoteAutoIncrementService } from './CreditNoteAutoIncrement.service';
|
||||
import { CreditNote } from '../models/CreditNote';
|
||||
import { CreateCreditNoteDto, EditCreditNoteDto } from '../dtos/CreditNote.dto';
|
||||
import { CreateCreditNoteDto, CreditNoteEntryDto, EditCreditNoteDto } from '../dtos/CreditNote.dto';
|
||||
|
||||
@Injectable()
|
||||
export class CommandCreditNoteDTOTransform {
|
||||
@@ -55,7 +55,7 @@ export class CommandCreditNoteDTOTransform {
|
||||
assocItemEntriesDefaultIndex,
|
||||
|
||||
// Associate the reference type to credit note entries.
|
||||
R.map((entry: ICreditNoteEntryNewDTO) => ({
|
||||
R.map((entry: CreditNoteEntryDto) => ({
|
||||
...entry,
|
||||
referenceType: 'CreditNote',
|
||||
})),
|
||||
|
||||
@@ -19,7 +19,7 @@ enum DiscountType {
|
||||
Amount = 'amount',
|
||||
}
|
||||
|
||||
class CreditNoteEntryDto extends ItemEntryDto {}
|
||||
export class CreditNoteEntryDto extends ItemEntryDto {}
|
||||
|
||||
class AttachmentDto {
|
||||
@IsString()
|
||||
|
||||
@@ -8,13 +8,11 @@ import {
|
||||
Put,
|
||||
} from '@nestjs/common';
|
||||
import { CustomersApplication } from './CustomersApplication.service';
|
||||
import {
|
||||
ICustomerEditDTO,
|
||||
ICustomerNewDTO,
|
||||
ICustomerOpeningBalanceEditDTO,
|
||||
} from './types/Customers.types';
|
||||
import { ICustomerOpeningBalanceEditDTO } from './types/Customers.types';
|
||||
import { PublicRoute } from '../Auth/Jwt.guard';
|
||||
import { ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||
import { CreateCustomerDto } from './dtos/CreateCustomer.dto';
|
||||
import { EditCustomerDto } from './dtos/EditCustomer.dto';
|
||||
|
||||
@Controller('customers')
|
||||
@ApiTags('customers')
|
||||
@@ -30,7 +28,7 @@ export class CustomersController {
|
||||
|
||||
@Post()
|
||||
@ApiOperation({ summary: 'Create a new customer.' })
|
||||
createCustomer(@Body() customerDTO: ICustomerNewDTO) {
|
||||
createCustomer(@Body() customerDTO: CreateCustomerDto) {
|
||||
return this.customersApplication.createCustomer(customerDTO);
|
||||
}
|
||||
|
||||
@@ -38,7 +36,7 @@ export class CustomersController {
|
||||
@ApiOperation({ summary: 'Edit the given customer.' })
|
||||
editCustomer(
|
||||
@Param('id') customerId: number,
|
||||
@Body() customerDTO: ICustomerEditDTO,
|
||||
@Body() customerDTO: EditCustomerDto,
|
||||
) {
|
||||
return this.customersApplication.editCustomer(customerId, customerDTO);
|
||||
}
|
||||
|
||||
@@ -4,12 +4,9 @@ import { CreateCustomer } from './commands/CreateCustomer.service';
|
||||
import { EditCustomer } from './commands/EditCustomer.service';
|
||||
import { DeleteCustomer } from './commands/DeleteCustomer.service';
|
||||
import { EditOpeningBalanceCustomer } from './commands/EditOpeningBalanceCustomer.service';
|
||||
import {
|
||||
ICustomerEditDTO,
|
||||
ICustomerNewDTO,
|
||||
ICustomerOpeningBalanceEditDTO,
|
||||
// ICustomersFilter,
|
||||
} from './types/Customers.types';
|
||||
import { ICustomerOpeningBalanceEditDTO } from './types/Customers.types';
|
||||
import { CreateCustomerDto } from './dtos/CreateCustomer.dto';
|
||||
import { EditCustomerDto } from './dtos/EditCustomer.dto';
|
||||
|
||||
@Injectable()
|
||||
export class CustomersApplication {
|
||||
@@ -36,7 +33,7 @@ export class CustomersApplication {
|
||||
* @param {ICustomerNewDTO} customerDTO
|
||||
* @returns {Promise<ICustomer>}
|
||||
*/
|
||||
public createCustomer = (customerDTO: ICustomerNewDTO) => {
|
||||
public createCustomer = (customerDTO: CreateCustomerDto) => {
|
||||
return this.createCustomerService.createCustomer(customerDTO);
|
||||
};
|
||||
|
||||
@@ -46,7 +43,7 @@ export class CustomersApplication {
|
||||
* @param {ICustomerEditDTO} customerDTO - Customer edit DTO.
|
||||
* @return {Promise<ICustomer>}
|
||||
*/
|
||||
public editCustomer = (customerId: number, customerDTO: ICustomerEditDTO) => {
|
||||
public editCustomer = (customerId: number, customerDTO: EditCustomerDto) => {
|
||||
return this.editCustomerService.editCustomer(customerId, customerDTO);
|
||||
};
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@ import { events } from '@/common/events/events';
|
||||
import {
|
||||
ICustomerEventCreatedPayload,
|
||||
ICustomerEventCreatingPayload,
|
||||
ICustomerNewDTO,
|
||||
} from '../types/Customers.types';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { CreateCustomerDto } from '../dtos/CreateCustomer.dto';
|
||||
|
||||
@Injectable()
|
||||
export class CreateCustomer {
|
||||
@@ -35,7 +35,7 @@ export class CreateCustomer {
|
||||
* @return {Promise<ICustomer>}
|
||||
*/
|
||||
public async createCustomer(
|
||||
customerDTO: ICustomerNewDTO,
|
||||
customerDTO: CreateCustomerDto,
|
||||
trx?: Knex.Transaction,
|
||||
): Promise<Customer> {
|
||||
// Transformes the customer DTO to customer object.
|
||||
|
||||
@@ -11,6 +11,7 @@ import { events } from '@/common/events/events';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { EditCustomerDto } from '../dtos/EditCustomer.dto';
|
||||
|
||||
@Injectable()
|
||||
export class EditCustomer {
|
||||
@@ -37,7 +38,7 @@ export class EditCustomer {
|
||||
*/
|
||||
public async editCustomer(
|
||||
customerId: number,
|
||||
customerDTO: ICustomerEditDTO,
|
||||
customerDTO: EditCustomerDto,
|
||||
): Promise<Customer> {
|
||||
// Retrieve the customer or throw not found error.
|
||||
const oldCustomer = await this.customerModel()
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
import { IsEmail, IsOptional, IsString } from 'class-validator';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
export class ContactAddressDto {
|
||||
@ApiProperty({ required: false, description: 'Billing address line 1' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
billingAddress1?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Billing address line 2' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
billingAddress2?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Billing address city' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
billingAddressCity?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Billing address country' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
billingAddressCountry?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Billing address email' })
|
||||
@IsOptional()
|
||||
@IsEmail()
|
||||
billingAddressEmail?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Billing address zipcode' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
billingAddressZipcode?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Billing address phone' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
billingAddressPhone?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Billing address state' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
billingAddressState?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Shipping address line 1' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
shippingAddress1?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Shipping address line 2' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
shippingAddress2?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Shipping address city' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
shippingAddressCity?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Shipping address country' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
shippingAddressCountry?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Shipping address email' })
|
||||
@IsOptional()
|
||||
@IsEmail()
|
||||
shippingAddressEmail?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Shipping address zipcode' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
shippingAddressZipcode?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Shipping address phone' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
shippingAddressPhone?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Shipping address state' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
shippingAddressState?: string;
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
import {
|
||||
IsBoolean,
|
||||
IsEmail,
|
||||
IsNotEmpty,
|
||||
IsNumber,
|
||||
IsOptional,
|
||||
IsString,
|
||||
} from 'class-validator';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { ContactAddressDto } from './ContactAddress.dto';
|
||||
|
||||
export class CreateCustomerDto extends ContactAddressDto {
|
||||
@ApiProperty({ required: true, description: 'Customer type' })
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
customerType: string;
|
||||
|
||||
@ApiProperty({ required: true, description: 'Currency code' })
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
currencyCode: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Opening balance' })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
openingBalance?: number;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Opening balance date' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
openingBalanceAt?: string;
|
||||
|
||||
@ApiProperty({
|
||||
required: false,
|
||||
description: 'Opening balance exchange rate',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
openingBalanceExchangeRate?: number;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Opening balance branch ID' })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
openingBalanceBranchId?: number;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Salutation' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
salutation?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'First name' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
firstName?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Last name' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
lastName?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Company name' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
companyName?: string;
|
||||
|
||||
@ApiProperty({ required: true, description: 'Display name' })
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
displayName: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Website' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
website?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Email' })
|
||||
@IsOptional()
|
||||
@IsEmail()
|
||||
email?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Work phone' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
workPhone?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Personal phone' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
personalPhone?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Note' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
note?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Active status', default: true })
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
active?: boolean;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import { IsBoolean, IsEmail, IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { ContactAddressDto } from './ContactAddress.dto';
|
||||
|
||||
export class EditCustomerDto extends ContactAddressDto {
|
||||
@ApiProperty({ required: true, description: 'Customer type' })
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
customerType: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Salutation' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
salutation?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'First name' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
firstName?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Last name' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
lastName?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Company name' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
companyName?: string;
|
||||
|
||||
@ApiProperty({ required: true, description: 'Display name' })
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
displayName: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Website' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
website?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Email' })
|
||||
@IsOptional()
|
||||
@IsEmail()
|
||||
email?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Work phone' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
workPhone?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Personal phone' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
personalPhone?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Note' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
note?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Active status' })
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
active?: boolean;
|
||||
}
|
||||
@@ -1,23 +1,5 @@
|
||||
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
|
||||
// import TenantModel from 'models/TenantModel';
|
||||
// import PaginationQueryBuilder from './Pagination';
|
||||
// import ModelSetting from './ModelSetting';
|
||||
// import CustomerSettings from './Customer.Settings';
|
||||
// import CustomViewBaseModel from './CustomViewBaseModel';
|
||||
// import { DEFAULT_VIEWS } from '@/services/Contacts/Customers/constants';
|
||||
// import ModelSearchable from './ModelSearchable';
|
||||
|
||||
// class CustomerQueryBuilder extends PaginationQueryBuilder {
|
||||
// constructor(...args) {
|
||||
// super(...args);
|
||||
|
||||
// this.onBuild((builder) => {
|
||||
// if (builder.isFind() || builder.isDelete() || builder.isUpdate()) {
|
||||
// builder.where('contact_service', 'customer');
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
export class Customer extends TenantBaseModel{
|
||||
contactService: string;
|
||||
|
||||
@@ -3,6 +3,8 @@ import { Customer } from '../models/Customer';
|
||||
import { IContactAddressDTO } from '@/modules/Contacts/types/Contacts.types';
|
||||
import { IDynamicListFilter } from '@/modules/DynamicListing/DynamicFilter/DynamicFilter.types';
|
||||
import { IFilterMeta, IPaginationMeta } from '@/interfaces/Model';
|
||||
import { CreateCustomerDto } from '../dtos/CreateCustomer.dto';
|
||||
import { EditCustomerDto } from '../dtos/EditCustomer.dto';
|
||||
|
||||
// Customer Interfaces.
|
||||
// ----------------------------------
|
||||
@@ -63,46 +65,38 @@ export interface GetCustomersResponse {
|
||||
// Customer Events.
|
||||
// ----------------------------------
|
||||
export interface ICustomerEventCreatedPayload {
|
||||
// tenantId: number;
|
||||
customerId: number;
|
||||
// authorizedUser: ISystemUser;
|
||||
customer: Customer;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
export interface ICustomerEventCreatingPayload {
|
||||
// tenantId: number;
|
||||
customerDTO: ICustomerNewDTO;
|
||||
customerDTO: CreateCustomerDto;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
export interface ICustomerEventEditedPayload {
|
||||
// tenantId: number
|
||||
customerId: number;
|
||||
customer: Customer;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface ICustomerEventEditingPayload {
|
||||
// tenantId: number;
|
||||
customerDTO: ICustomerEditDTO;
|
||||
customerDTO: EditCustomerDto;
|
||||
customerId: number;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface ICustomerDeletingPayload {
|
||||
// tenantId: number;
|
||||
customerId: number;
|
||||
oldCustomer: Customer;
|
||||
}
|
||||
|
||||
export interface ICustomerEventDeletedPayload {
|
||||
// tenantId: number;
|
||||
customerId: number;
|
||||
oldCustomer: Customer;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
export interface ICustomerEventCreatingPayload {
|
||||
// tenantId: number;
|
||||
customerDTO: ICustomerNewDTO;
|
||||
customerDTO: CreateCustomerDto;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
export enum CustomerAction {
|
||||
@@ -141,13 +135,11 @@ export interface ICustomerOpeningBalanceEditedPayload {
|
||||
|
||||
|
||||
export interface ICustomerActivatingPayload {
|
||||
// tenantId: number;
|
||||
trx: Knex.Transaction,
|
||||
oldCustomer: Customer;
|
||||
}
|
||||
|
||||
export interface ICustomerActivatedPayload {
|
||||
// tenantId: number;
|
||||
trx?: Knex.Transaction;
|
||||
oldCustomer: Customer;
|
||||
customer: Customer;
|
||||
|
||||
@@ -9,13 +9,10 @@ import {
|
||||
Query,
|
||||
} from '@nestjs/common';
|
||||
import { ExpensesApplication } from './ExpensesApplication.service';
|
||||
import {
|
||||
IExpenseCreateDTO,
|
||||
IExpenseEditDTO,
|
||||
} from './interfaces/Expenses.interface';
|
||||
import { PublicRoute } from '../Auth/Jwt.guard';
|
||||
import { IExpensesFilter } from './Expenses.types';
|
||||
import { ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||
import { CreateExpenseDto, EditExpenseDto } from './dtos/Expense.dto';
|
||||
|
||||
@Controller('expenses')
|
||||
@ApiTags('expenses')
|
||||
@@ -29,7 +26,7 @@ export class ExpensesController {
|
||||
*/
|
||||
@Post()
|
||||
@ApiOperation({ summary: 'Create a new expense transaction.' })
|
||||
public createExpense(@Body() expenseDTO: IExpenseCreateDTO) {
|
||||
public createExpense(@Body() expenseDTO: CreateExpenseDto) {
|
||||
return this.expensesApplication.createExpense(expenseDTO);
|
||||
}
|
||||
|
||||
@@ -42,7 +39,7 @@ export class ExpensesController {
|
||||
@ApiOperation({ summary: 'Edit the given expense transaction.' })
|
||||
public editExpense(
|
||||
@Param('id') expenseId: number,
|
||||
@Body() expenseDTO: IExpenseEditDTO,
|
||||
@Body() expenseDTO: EditExpenseDto,
|
||||
) {
|
||||
return this.expensesApplication.editExpense(expenseId, expenseDTO);
|
||||
}
|
||||
|
||||
@@ -4,12 +4,9 @@ import { EditExpense } from './commands/EditExpense.service';
|
||||
import { DeleteExpense } from './commands/DeleteExpense.service';
|
||||
import { PublishExpense } from './commands/PublishExpense.service';
|
||||
import { GetExpenseService } from './queries/GetExpense.service';
|
||||
import {
|
||||
IExpenseCreateDTO,
|
||||
IExpenseEditDTO,
|
||||
IExpensesFilter,
|
||||
} from './interfaces/Expenses.interface';
|
||||
import { IExpensesFilter } from './interfaces/Expenses.interface';
|
||||
import { GetExpensesService } from './queries/GetExpenses.service';
|
||||
import { CreateExpenseDto, EditExpenseDto } from './dtos/Expense.dto';
|
||||
|
||||
@Injectable()
|
||||
export class ExpensesApplication {
|
||||
@@ -24,55 +21,55 @@ export class ExpensesApplication {
|
||||
|
||||
/**
|
||||
* Create a new expense transaction.
|
||||
* @param {IExpenseDTO} expenseDTO
|
||||
* @param {CreateExpenseDto} expenseDTO
|
||||
* @returns {Promise<Expense>}
|
||||
*/
|
||||
public createExpense = (expenseDTO: IExpenseCreateDTO) => {
|
||||
public createExpense(expenseDTO: CreateExpenseDto) {
|
||||
return this.createExpenseService.newExpense(expenseDTO);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits the given expense transaction.
|
||||
* @param {number} expenseId - Expense id.
|
||||
* @param {IExpenseEditDTO} expenseDTO
|
||||
* @param {EditExpenseDto} expenseDTO
|
||||
* @returns {Promise<Expense>}
|
||||
*/
|
||||
public editExpense = (expenseId: number, expenseDTO: IExpenseEditDTO) => {
|
||||
public editExpense(expenseId: number, expenseDTO: EditExpenseDto) {
|
||||
return this.editExpenseService.editExpense(expenseId, expenseDTO);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the given expense.
|
||||
* @param {number} expenseId - Expense id.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public deleteExpense = (expenseId: number) => {
|
||||
public deleteExpense(expenseId: number) {
|
||||
return this.deleteExpenseService.deleteExpense(expenseId);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Publishes the given expense.
|
||||
* @param {number} expenseId - Expense id.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public publishExpense = (expenseId: number) => {
|
||||
public publishExpense(expenseId: number) {
|
||||
return this.publishExpenseService.publishExpense(expenseId);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the given expense details.
|
||||
* @param {number} expenseId -Expense id.
|
||||
* @param {number} expenseId -Expense id.
|
||||
* @return {Promise<Expense>}
|
||||
*/
|
||||
public getExpense = (expenseId: number) => {
|
||||
public getExpense(expenseId: number) {
|
||||
return this.getExpenseService.getExpense(expenseId);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve expenses paginated list.
|
||||
* @param {IExpensesFilter} expensesFilter
|
||||
*/
|
||||
public getExpenses = (filterDTO: IExpensesFilter) => {
|
||||
public getExpenses(filterDTO: IExpensesFilter) {
|
||||
return this.getExpensesService.getExpensesList(filterDTO);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,11 @@ import { Injectable } from '@nestjs/common';
|
||||
import { omit, sumBy } from 'lodash';
|
||||
import * as moment from 'moment';
|
||||
import * as R from 'ramda';
|
||||
import {
|
||||
IExpenseCreateDTO,
|
||||
IExpenseEditDTO,
|
||||
} from '../interfaces/Expenses.interface';
|
||||
import { BranchTransactionDTOTransformer } from '@/modules/Branches/integrations/BranchTransactionDTOTransform';
|
||||
import { Expense } from '../models/Expense.model';
|
||||
import { assocItemEntriesDefaultIndex } from '@/utils/associate-item-entries-index';
|
||||
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
|
||||
import { CreateExpenseDto, EditExpenseDto } from '../dtos/Expense.dto';
|
||||
|
||||
@Injectable()
|
||||
export class ExpenseDTOTransformer {
|
||||
@@ -28,7 +25,7 @@ export class ExpenseDTOTransformer {
|
||||
* @return {number}
|
||||
*/
|
||||
private getExpenseLandedCostAmount = (
|
||||
expenseDTO: IExpenseCreateDTO | IExpenseEditDTO,
|
||||
expenseDTO: CreateExpenseDto | EditExpenseDto,
|
||||
): number => {
|
||||
const landedCostEntries = expenseDTO.categories.filter((entry) => {
|
||||
return entry.landedCost === true;
|
||||
@@ -52,7 +49,7 @@ export class ExpenseDTOTransformer {
|
||||
* @return {IExpense}
|
||||
*/
|
||||
private expenseDTOToModel(
|
||||
expenseDTO: IExpenseCreateDTO | IExpenseEditDTO,
|
||||
expenseDTO: CreateExpenseDto | EditExpenseDto,
|
||||
): Expense {
|
||||
const landedCostAmount = this.getExpenseLandedCostAmount(expenseDTO);
|
||||
const totalAmount = this.getExpenseCategoriesTotal(expenseDTO.categories);
|
||||
@@ -85,7 +82,7 @@ export class ExpenseDTOTransformer {
|
||||
* @returns {Promise<Expense>}
|
||||
*/
|
||||
public expenseCreateDTO = async (
|
||||
expenseDTO: IExpenseCreateDTO,
|
||||
expenseDTO: CreateExpenseDto | EditExpenseDto,
|
||||
): Promise<Partial<Expense>> => {
|
||||
const initialDTO = this.expenseDTOToModel(expenseDTO);
|
||||
const tenant = await this.tenancyContext.getTenant(true);
|
||||
@@ -104,13 +101,11 @@ export class ExpenseDTOTransformer {
|
||||
|
||||
/**
|
||||
* Transformes the expense edit DTO.
|
||||
* @param {number} tenantId
|
||||
* @param {IExpenseEditDTO} expenseDTO
|
||||
* @param {ISystemUser} user
|
||||
* @returns {IExpense}
|
||||
* @param {EditExpenseDto} expenseDTO
|
||||
* @returns {Promise<Expense>}
|
||||
*/
|
||||
public expenseEditDTO = async (
|
||||
expenseDTO: IExpenseEditDTO,
|
||||
expenseDTO: EditExpenseDto,
|
||||
): Promise<Expense> => {
|
||||
return this.expenseDTOToModel(expenseDTO);
|
||||
};
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import { sumBy, difference } from 'lodash';
|
||||
import { ERRORS, SUPPORTED_EXPENSE_PAYMENT_ACCOUNT_TYPES } from '../constants';
|
||||
import {
|
||||
IExpenseCreateDTO,
|
||||
IExpenseEditDTO,
|
||||
} from '../interfaces/Expenses.interface';
|
||||
import { ACCOUNT_ROOT_TYPE } from '@/constants/accounts';
|
||||
import { Account } from '@/modules/Accounts/models/Account.model';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Expense } from '../models/Expense.model';
|
||||
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||
import { CreateExpenseDto, EditExpenseDto } from '../dtos/Expense.dto';
|
||||
|
||||
@Injectable()
|
||||
export class CommandExpenseValidator {
|
||||
@@ -18,7 +15,7 @@ export class CommandExpenseValidator {
|
||||
* @throws {ServiceError}
|
||||
*/
|
||||
public validateCategoriesNotEqualZero = (
|
||||
expenseDTO: IExpenseCreateDTO | IExpenseEditDTO,
|
||||
expenseDTO: CreateExpenseDto | EditExpenseDto,
|
||||
) => {
|
||||
const totalAmount = sumBy(expenseDTO.categories, 'amount') || 0;
|
||||
|
||||
@@ -30,7 +27,6 @@ export class CommandExpenseValidator {
|
||||
/**
|
||||
* Retrieve expense accounts or throw error in case one of the given accounts
|
||||
* not found not the storage.
|
||||
* @param {Array<Account>} tenantId
|
||||
* @param {number} expenseAccountsIds
|
||||
* @throws {ServiceError}
|
||||
* @returns {Promise<IAccount[]>}
|
||||
@@ -40,7 +36,6 @@ export class CommandExpenseValidator {
|
||||
DTOAccountsIds: number[],
|
||||
) {
|
||||
const storedExpenseAccountsIds = expenseAccounts.map((a: Account) => a.id);
|
||||
|
||||
const notStoredAccountsIds = difference(
|
||||
DTOAccountsIds,
|
||||
storedExpenseAccountsIds,
|
||||
@@ -84,7 +79,6 @@ export class CommandExpenseValidator {
|
||||
/**
|
||||
* Validates the expense has not associated landed cost
|
||||
* references to the given expense.
|
||||
* @param {number} tenantId
|
||||
* @param {number} expenseId
|
||||
*/
|
||||
public async validateNoAssociatedLandedCost(expenseId: number) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Knex } from 'knex';
|
||||
import {
|
||||
IExpenseCreateDTO,
|
||||
IExpenseCreatedPayload,
|
||||
IExpenseCreatingPayload,
|
||||
} from '../interfaces/Expenses.interface';
|
||||
@@ -13,6 +12,7 @@ import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { events } from '@/common/events/events';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { CreateExpenseDto } from '../dtos/Expense.dto';
|
||||
|
||||
@Injectable()
|
||||
export class CreateExpense {
|
||||
@@ -41,7 +41,7 @@ export class CreateExpense {
|
||||
* Authorize before create a new expense transaction.
|
||||
* @param {IExpenseDTO} expenseDTO
|
||||
*/
|
||||
private authorize = async (expenseDTO: IExpenseCreateDTO) => {
|
||||
private authorize = async (expenseDTO: CreateExpenseDto) => {
|
||||
// Validate payment account existance on the storage.
|
||||
const paymentAccount = await this.accountModel()
|
||||
.query()
|
||||
@@ -86,7 +86,7 @@ export class CreateExpense {
|
||||
* @param {IExpenseDTO} expenseDTO
|
||||
*/
|
||||
public newExpense = async (
|
||||
expenseDTO: IExpenseCreateDTO,
|
||||
expenseDTO: CreateExpenseDto,
|
||||
trx?: Knex.Transaction,
|
||||
): Promise<Expense> => {
|
||||
// Authorize before create a new expense.
|
||||
|
||||
@@ -3,17 +3,16 @@ import { Knex } from 'knex';
|
||||
import {
|
||||
IExpenseEventEditPayload,
|
||||
IExpenseEventEditingPayload,
|
||||
IExpenseEditDTO,
|
||||
} from '../interfaces/Expenses.interface';
|
||||
import { CommandExpenseValidator } from './CommandExpenseValidator.service';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { ExpenseDTOTransformer } from './CommandExpenseDTO.transformer';
|
||||
// import { EntriesService } from '@/services/Entries';
|
||||
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { Account } from '@/modules/Accounts/models/Account.model';
|
||||
import { Expense } from '../models/Expense.model';
|
||||
import { events } from '@/common/events/events';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { EditExpenseDto } from '../dtos/Expense.dto';
|
||||
|
||||
@Injectable()
|
||||
export class EditExpense {
|
||||
@@ -30,7 +29,6 @@ export class EditExpense {
|
||||
private uow: UnitOfWork,
|
||||
private validator: CommandExpenseValidator,
|
||||
private transformDTO: ExpenseDTOTransformer,
|
||||
// private entriesService: EntriesService,
|
||||
@Inject(Expense.name)
|
||||
private expenseModel: TenantModelProxy<typeof Expense>,
|
||||
|
||||
@@ -40,11 +38,11 @@ export class EditExpense {
|
||||
|
||||
/**
|
||||
* Authorize the DTO before editing expense transaction.
|
||||
* @param {IExpenseEditDTO} expenseDTO
|
||||
* @param {EditExpenseDto} expenseDTO
|
||||
*/
|
||||
public authorize = async (
|
||||
oldExpense: Expense,
|
||||
expenseDTO: IExpenseEditDTO,
|
||||
expenseDTO: EditExpenseDto,
|
||||
) => {
|
||||
// Validate payment account existance on the storage.
|
||||
const paymentAccount = await this.accountModel()
|
||||
@@ -102,7 +100,7 @@ export class EditExpense {
|
||||
*/
|
||||
public async editExpense(
|
||||
expenseId: number,
|
||||
expenseDTO: IExpenseEditDTO,
|
||||
expenseDTO: EditExpenseDto,
|
||||
): Promise<Expense> {
|
||||
// Retrieves the expense model or throw not found error.
|
||||
const oldExpense = await this.expenseModel()
|
||||
|
||||
@@ -1,3 +1,166 @@
|
||||
export class CreateExpenseDto {}
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { Type } from 'class-transformer';
|
||||
import {
|
||||
IsArray,
|
||||
IsBoolean,
|
||||
IsDate,
|
||||
IsInt,
|
||||
IsNotEmpty,
|
||||
IsNumber,
|
||||
IsOptional,
|
||||
IsString,
|
||||
MaxLength,
|
||||
ValidateNested,
|
||||
} from 'class-validator';
|
||||
|
||||
export class EditExpenseDto {}
|
||||
class AttachmentDto {
|
||||
@IsString()
|
||||
key: string;
|
||||
}
|
||||
|
||||
export class ExpenseCategoryDto {
|
||||
@IsInt()
|
||||
@IsNotEmpty()
|
||||
index: number;
|
||||
|
||||
@IsInt()
|
||||
@IsNotEmpty()
|
||||
expenseAccountId: number;
|
||||
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
amount?: number;
|
||||
|
||||
@IsString()
|
||||
@MaxLength(255)
|
||||
@IsOptional()
|
||||
description?: string;
|
||||
|
||||
@IsBoolean()
|
||||
@IsOptional()
|
||||
landedCost?: boolean;
|
||||
|
||||
@IsInt()
|
||||
@IsOptional()
|
||||
projectId?: number;
|
||||
}
|
||||
|
||||
export class CommandExpenseDto {
|
||||
@IsString()
|
||||
@MaxLength(255)
|
||||
@IsOptional()
|
||||
@ApiProperty({
|
||||
description: 'The reference number of the expense',
|
||||
example: 'INV-123456',
|
||||
})
|
||||
referenceNo?: string;
|
||||
|
||||
@IsDate()
|
||||
@IsNotEmpty()
|
||||
@ApiProperty({
|
||||
description: 'The payment date of the expense',
|
||||
example: '2021-01-01',
|
||||
})
|
||||
paymentDate: Date;
|
||||
|
||||
@IsInt()
|
||||
@IsNotEmpty()
|
||||
@ApiProperty({
|
||||
description: 'The payment account id of the expense',
|
||||
example: 1,
|
||||
})
|
||||
paymentAccountId: number;
|
||||
|
||||
@IsString()
|
||||
@MaxLength(1000)
|
||||
@IsOptional()
|
||||
@ApiProperty({
|
||||
description: 'The description of the expense',
|
||||
example: 'This is a description',
|
||||
})
|
||||
description?: string;
|
||||
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
@ApiProperty({
|
||||
description: 'The exchange rate of the expense',
|
||||
example: 1,
|
||||
})
|
||||
exchangeRate?: number;
|
||||
|
||||
@IsString()
|
||||
@MaxLength(3)
|
||||
@IsOptional()
|
||||
@ApiProperty({
|
||||
description: 'The currency code of the expense',
|
||||
example: 'USD',
|
||||
})
|
||||
currencyCode?: string;
|
||||
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
@ApiProperty({
|
||||
description: 'The exchange rate of the expense',
|
||||
example: 1,
|
||||
})
|
||||
exchange_rate?: number;
|
||||
|
||||
@IsBoolean()
|
||||
@IsOptional()
|
||||
@ApiProperty({
|
||||
description: 'The publish status of the expense',
|
||||
example: true,
|
||||
})
|
||||
publish?: boolean;
|
||||
|
||||
@IsInt()
|
||||
@IsOptional()
|
||||
@ApiProperty({
|
||||
description: 'The payee id of the expense',
|
||||
example: 1,
|
||||
})
|
||||
payeeId?: number;
|
||||
|
||||
@IsInt()
|
||||
@IsOptional()
|
||||
@ApiProperty({
|
||||
description: 'The branch id of the expense',
|
||||
example: 1,
|
||||
})
|
||||
branchId?: number;
|
||||
|
||||
@IsArray()
|
||||
@ValidateNested({ each: true })
|
||||
@Type(() => ExpenseCategoryDto)
|
||||
@ApiProperty({
|
||||
description: 'The categories of the expense',
|
||||
example: [
|
||||
{
|
||||
index: 1,
|
||||
expenseAccountId: 1,
|
||||
amount: 100,
|
||||
description: 'This is a description',
|
||||
landedCost: true,
|
||||
projectId: 1,
|
||||
},
|
||||
],
|
||||
})
|
||||
categories: ExpenseCategoryDto[];
|
||||
|
||||
@IsArray()
|
||||
@ValidateNested({ each: true })
|
||||
@Type(() => AttachmentDto)
|
||||
@IsOptional()
|
||||
@ApiProperty({
|
||||
description: 'The attachments of the expense',
|
||||
example: [
|
||||
{
|
||||
key: '123456',
|
||||
},
|
||||
],
|
||||
})
|
||||
attachments?: AttachmentDto[];
|
||||
}
|
||||
|
||||
export class CreateExpenseDto extends CommandExpenseDto {}
|
||||
export class EditExpenseDto extends CommandExpenseDto {}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { IFilterRole } from '@/modules/DynamicListing/DynamicFilter/DynamicFilter.types';
|
||||
import { Knex } from 'knex';
|
||||
import { Expense } from '../models/Expense.model';
|
||||
import { CreateExpenseDto, EditExpenseDto } from '../dtos/Expense.dto';
|
||||
|
||||
// import { AttachmentLinkDTO } from '../Attachments/Attachments';
|
||||
|
||||
@@ -20,26 +21,6 @@ export interface IExpensesFilter {
|
||||
filterQuery?: (query: any) => void;
|
||||
}
|
||||
|
||||
export interface IExpenseCommonDTO {
|
||||
currencyCode: string;
|
||||
exchangeRate?: number;
|
||||
description?: string;
|
||||
paymentAccountId: number;
|
||||
peyeeId?: number;
|
||||
referenceNo?: string;
|
||||
publish: boolean;
|
||||
userId: number;
|
||||
paymentDate: Date;
|
||||
payeeId: number;
|
||||
categories: IExpenseCategoryDTO[];
|
||||
|
||||
branchId?: number;
|
||||
// attachments?: AttachmentLinkDTO[];
|
||||
}
|
||||
|
||||
export interface IExpenseCreateDTO extends IExpenseCommonDTO {}
|
||||
export interface IExpenseEditDTO extends IExpenseCommonDTO {}
|
||||
|
||||
export interface IExpenseCategoryDTO {
|
||||
id?: number;
|
||||
expenseAccountId: number;
|
||||
@@ -52,55 +33,44 @@ export interface IExpenseCategoryDTO {
|
||||
}
|
||||
|
||||
export interface IExpenseCreatingPayload {
|
||||
expenseDTO: CreateExpenseDto;
|
||||
trx: Knex.Transaction;
|
||||
tenantId: number;
|
||||
expenseDTO: IExpenseCreateDTO;
|
||||
}
|
||||
|
||||
export interface IExpenseEventEditingPayload {
|
||||
tenantId: number;
|
||||
oldExpense: Expense;
|
||||
expenseDTO: IExpenseEditDTO;
|
||||
expenseDTO: EditExpenseDto;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
export interface IExpenseCreatedPayload {
|
||||
tenantId: number;
|
||||
expenseId: number;
|
||||
// authorizedUser: ISystemUser;
|
||||
expense: Expense;
|
||||
expenseDTO: IExpenseCreateDTO;
|
||||
expenseDTO: CreateExpenseDto;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface IExpenseEventEditPayload {
|
||||
tenantId: number;
|
||||
expenseId: number;
|
||||
expense: Expense;
|
||||
expenseDTO: IExpenseEditDTO;
|
||||
// authorizedUser: ISystemUser;
|
||||
expenseDTO: EditExpenseDto;
|
||||
oldExpense: Expense;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface IExpenseEventDeletePayload {
|
||||
tenantId: number;
|
||||
expenseId: number;
|
||||
// authorizedUser: ISystemUser;
|
||||
oldExpense: Expense;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface IExpenseDeletingPayload {
|
||||
trx: Knex.Transaction;
|
||||
tenantId: number;
|
||||
oldExpense: Expense;
|
||||
}
|
||||
export interface IExpenseEventPublishedPayload {
|
||||
tenantId: number;
|
||||
expenseId: number;
|
||||
oldExpense: Expense;
|
||||
expense: Expense;
|
||||
// authorizedUser: ISystemUser;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,95 +13,190 @@ import {
|
||||
IsNotEmpty,
|
||||
} from 'class-validator';
|
||||
import { Type } from 'class-transformer';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
export class CommandItemDto {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@MaxLength(255)
|
||||
@ApiProperty({ description: 'Item name', example: 'Office Chair' })
|
||||
name: string;
|
||||
|
||||
@IsString()
|
||||
@IsIn(['service', 'non-inventory', 'inventory'])
|
||||
@ApiProperty({
|
||||
description: 'Item type',
|
||||
enum: ['service', 'non-inventory', 'inventory'],
|
||||
example: 'inventory',
|
||||
})
|
||||
type: 'service' | 'non-inventory' | 'inventory';
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@MaxLength(255)
|
||||
@ApiProperty({
|
||||
description: 'Item code/SKU',
|
||||
required: false,
|
||||
example: 'ITEM-001',
|
||||
})
|
||||
code?: string;
|
||||
|
||||
// Purchase attributes
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
@ApiProperty({
|
||||
description: 'Whether the item can be purchased',
|
||||
required: false,
|
||||
example: true,
|
||||
})
|
||||
purchasable?: boolean;
|
||||
|
||||
@IsOptional()
|
||||
@IsNumber({ maxDecimalPlaces: 3 })
|
||||
@Min(0)
|
||||
@ValidateIf((o) => o.purchasable === true)
|
||||
@ApiProperty({
|
||||
description: 'Cost price of the item',
|
||||
required: false,
|
||||
minimum: 0,
|
||||
example: 100.5,
|
||||
})
|
||||
costPrice?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@Min(0)
|
||||
@ValidateIf((o) => o.purchasable === true)
|
||||
@ApiProperty({
|
||||
description: 'ID of the cost account',
|
||||
required: false,
|
||||
minimum: 0,
|
||||
example: 1,
|
||||
})
|
||||
costAccountId?: number;
|
||||
|
||||
// Sell attributes
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
@ApiProperty({
|
||||
description: 'Whether the item can be sold',
|
||||
required: false,
|
||||
example: true,
|
||||
})
|
||||
sellable?: boolean;
|
||||
|
||||
@IsOptional()
|
||||
@IsNumber({ maxDecimalPlaces: 3 })
|
||||
@Min(0)
|
||||
@ValidateIf((o) => o.sellable === true)
|
||||
@ApiProperty({
|
||||
description: 'Selling price of the item',
|
||||
required: false,
|
||||
minimum: 0,
|
||||
example: 150.75,
|
||||
})
|
||||
sellPrice?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@Min(0)
|
||||
@ValidateIf((o) => o.sellable === true)
|
||||
@ApiProperty({
|
||||
description: 'ID of the sell account',
|
||||
required: false,
|
||||
minimum: 0,
|
||||
example: 2,
|
||||
})
|
||||
sellAccountId?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@Min(0)
|
||||
@ValidateIf((o) => o.type === 'inventory')
|
||||
@ApiProperty({
|
||||
description: 'ID of the inventory account (required for inventory items)',
|
||||
required: false,
|
||||
minimum: 0,
|
||||
example: 3,
|
||||
})
|
||||
inventoryAccountId?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@ApiProperty({
|
||||
description: 'Description shown on sales documents',
|
||||
required: false,
|
||||
example: 'High-quality ergonomic office chair',
|
||||
})
|
||||
sellDescription?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@ApiProperty({
|
||||
description: 'Description shown on purchase documents',
|
||||
required: false,
|
||||
example: 'Ergonomic office chair with adjustable height',
|
||||
})
|
||||
purchaseDescription?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@ApiProperty({
|
||||
description: 'ID of the tax rate applied to sales',
|
||||
required: false,
|
||||
example: 1,
|
||||
})
|
||||
sellTaxRateId?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@ApiProperty({
|
||||
description: 'ID of the tax rate applied to purchases',
|
||||
required: false,
|
||||
example: 1,
|
||||
})
|
||||
purchaseTaxRateId?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@Min(0)
|
||||
@ApiProperty({
|
||||
description: 'ID of the item category',
|
||||
required: false,
|
||||
minimum: 0,
|
||||
example: 5,
|
||||
})
|
||||
categoryId?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@ApiProperty({
|
||||
description: 'Additional notes about the item',
|
||||
required: false,
|
||||
example: 'Available in multiple colors',
|
||||
})
|
||||
note?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
@ApiProperty({
|
||||
description: 'Whether the item is active',
|
||||
required: false,
|
||||
default: true,
|
||||
example: true,
|
||||
})
|
||||
active?: boolean;
|
||||
|
||||
@IsOptional()
|
||||
@IsArray()
|
||||
@Type(() => Number)
|
||||
@IsInt({ each: true })
|
||||
@ApiProperty({
|
||||
description: 'IDs of media files associated with the item',
|
||||
required: false,
|
||||
type: [Number],
|
||||
example: [1, 2, 3],
|
||||
})
|
||||
mediaIds?: number[];
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { ItemEntryDto } from '@/modules/TransactionItemEntry/dto/ItemEntry.dto';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { Type } from 'class-transformer';
|
||||
import {
|
||||
IsArray,
|
||||
IsBoolean,
|
||||
IsDate,
|
||||
IsEnum,
|
||||
IsNotEmpty,
|
||||
IsNumber,
|
||||
IsOptional,
|
||||
IsString,
|
||||
@@ -26,18 +28,35 @@ class AttachmentDto {
|
||||
}
|
||||
export class CommandSaleEstimateDto {
|
||||
@IsNumber()
|
||||
@IsNotEmpty()
|
||||
@ApiProperty({
|
||||
description: 'The id of the customer',
|
||||
example: 1,
|
||||
})
|
||||
customerId: number;
|
||||
|
||||
@IsDate()
|
||||
@Type(() => Date)
|
||||
@ApiProperty({
|
||||
description: 'The date of the estimate',
|
||||
example: '2021-01-01',
|
||||
})
|
||||
estimateDate: Date;
|
||||
|
||||
@IsDate()
|
||||
@Type(() => Date)
|
||||
@ApiProperty({
|
||||
description: 'The expiration date of the estimate',
|
||||
example: '2021-01-01',
|
||||
})
|
||||
expirationDate: Date;
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
@ApiProperty({
|
||||
description: 'The reference of the estimate',
|
||||
example: '123456',
|
||||
})
|
||||
reference?: string;
|
||||
|
||||
@IsString()
|
||||
@@ -50,53 +69,111 @@ export class CommandSaleEstimateDto {
|
||||
@IsNumber()
|
||||
@Min(0.01)
|
||||
@IsOptional()
|
||||
@ApiProperty({
|
||||
description: 'The exchange rate of the estimate',
|
||||
example: 1,
|
||||
})
|
||||
exchangeRate?: number;
|
||||
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
@ApiProperty({
|
||||
description: 'The id of the warehouse',
|
||||
example: 1,
|
||||
})
|
||||
warehouseId?: number;
|
||||
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
@ApiProperty({
|
||||
description: 'The id of the branch',
|
||||
example: 1,
|
||||
})
|
||||
branchId?: number;
|
||||
|
||||
@IsArray()
|
||||
@MinLength(1)
|
||||
@ValidateNested({ each: true })
|
||||
@Type(() => SaleEstimateEntryDto)
|
||||
@ApiProperty({
|
||||
description: 'The entries of the estimate',
|
||||
example: [
|
||||
{
|
||||
index: 1,
|
||||
itemId: 1,
|
||||
description: 'This is a description',
|
||||
quantity: 100,
|
||||
cost: 100,
|
||||
},
|
||||
],
|
||||
})
|
||||
entries: SaleEstimateEntryDto[];
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
@ApiProperty({
|
||||
description: 'The note of the estimate',
|
||||
example: 'This is a note',
|
||||
})
|
||||
note?: string;
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
@ApiProperty({
|
||||
description: 'The terms and conditions of the estimate',
|
||||
example: 'This is a terms and conditions',
|
||||
})
|
||||
termsConditions?: string;
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
@ApiProperty({
|
||||
description: 'The email to send the estimate to',
|
||||
example: 'test@test.com',
|
||||
})
|
||||
sendToEmail?: string;
|
||||
|
||||
@IsArray()
|
||||
@IsOptional()
|
||||
@ValidateNested({ each: true })
|
||||
@Type(() => AttachmentDto)
|
||||
attachments?: AttachmentDto[];
|
||||
|
||||
@ApiProperty({
|
||||
description: 'The attachments of the estimate',
|
||||
example: [
|
||||
{
|
||||
key: '123456',
|
||||
},
|
||||
],
|
||||
})
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
@ApiProperty({
|
||||
description: 'The id of the pdf template',
|
||||
example: 1,
|
||||
})
|
||||
pdfTemplateId?: number;
|
||||
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
@ApiProperty({
|
||||
description: 'The discount of the estimate',
|
||||
example: 1,
|
||||
})
|
||||
discount?: number;
|
||||
|
||||
@IsEnum(DiscountType)
|
||||
@ApiProperty({
|
||||
description: 'The type of the discount',
|
||||
example: DiscountType.Amount,
|
||||
})
|
||||
discountType: DiscountType = DiscountType.Amount;
|
||||
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
@ApiProperty({
|
||||
description: 'The adjustment of the estimate',
|
||||
example: 1,
|
||||
})
|
||||
adjustment?: number;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { ItemEntryDto } from '@/modules/TransactionItemEntry/dto/ItemEntry.dto';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { Type } from 'class-transformer';
|
||||
import {
|
||||
IsArray,
|
||||
@@ -31,89 +32,159 @@ class PaymentMethodDto {
|
||||
class CommandSaleInvoiceDto {
|
||||
@IsInt()
|
||||
@IsNotEmpty()
|
||||
@ApiProperty({ description: 'Customer ID', example: 1 })
|
||||
customerId: number;
|
||||
|
||||
@IsDate()
|
||||
@Type(() => Date)
|
||||
@IsNotEmpty()
|
||||
@ApiProperty({ description: 'Invoice date', example: '2023-01-01T00:00:00Z' })
|
||||
invoiceDate: Date;
|
||||
|
||||
@IsDate()
|
||||
@Type(() => Date)
|
||||
@IsNotEmpty()
|
||||
@ApiProperty({ description: 'Due date', example: '2023-01-15T00:00:00Z' })
|
||||
dueDate: Date;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@ApiProperty({
|
||||
description: 'Invoice number',
|
||||
required: false,
|
||||
example: 'INV-001',
|
||||
})
|
||||
invoiceNo?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@ApiProperty({
|
||||
description: 'Reference number',
|
||||
required: false,
|
||||
example: 'REF-001',
|
||||
})
|
||||
referenceNo?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
@ApiProperty({
|
||||
description: 'Whether the invoice is delivered',
|
||||
default: false,
|
||||
required: false,
|
||||
})
|
||||
delivered: boolean = false;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@ApiProperty({
|
||||
description: 'Invoice message',
|
||||
required: false,
|
||||
example: 'Thank you for your business',
|
||||
})
|
||||
invoiceMessage?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@ApiProperty({
|
||||
description: 'Terms and conditions',
|
||||
required: false,
|
||||
example: 'Payment due within 14 days',
|
||||
})
|
||||
termsConditions?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
@Min(0)
|
||||
@ApiProperty({
|
||||
description: 'Exchange rate',
|
||||
required: false,
|
||||
minimum: 0,
|
||||
example: 1.0,
|
||||
})
|
||||
exchangeRate?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@ApiProperty({ description: 'Warehouse ID', required: false, example: 1 })
|
||||
warehouseId?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@ApiProperty({ description: 'Branch ID', required: false, example: 1 })
|
||||
branchId?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@ApiProperty({ description: 'Project ID', required: false, example: 1 })
|
||||
projectId?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
@ApiProperty({
|
||||
description: 'Whether tax is inclusive',
|
||||
required: false,
|
||||
example: false,
|
||||
})
|
||||
isInclusiveTax?: boolean;
|
||||
|
||||
@IsArray()
|
||||
@ValidateNested({ each: true })
|
||||
@Type(() => ItemEntryDto)
|
||||
@MinLength(1)
|
||||
@ApiProperty({
|
||||
description: 'Invoice line items',
|
||||
type: [ItemEntryDto],
|
||||
minItems: 1,
|
||||
})
|
||||
entries: ItemEntryDto[];
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@ApiProperty({ description: 'PDF template ID', required: false, example: 1 })
|
||||
pdfTemplateId?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsArray()
|
||||
@ValidateNested({ each: true })
|
||||
@Type(() => PaymentMethodDto)
|
||||
@ApiProperty({
|
||||
description: 'Payment methods',
|
||||
type: [PaymentMethodDto],
|
||||
required: false,
|
||||
})
|
||||
paymentMethods?: PaymentMethodDto[];
|
||||
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
@ApiProperty({ description: 'Discount value', required: false, example: 10 })
|
||||
discount?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsEnum(DiscountType)
|
||||
@ApiProperty({
|
||||
description: 'Discount type',
|
||||
enum: DiscountType,
|
||||
required: false,
|
||||
example: DiscountType.Percentage,
|
||||
})
|
||||
discountType?: DiscountType;
|
||||
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
@ApiProperty({
|
||||
description: 'Adjustment amount',
|
||||
required: false,
|
||||
example: 5,
|
||||
})
|
||||
adjustment?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@ApiProperty({
|
||||
description: 'ID of the estimate this invoice is created from',
|
||||
required: false,
|
||||
example: 1,
|
||||
})
|
||||
fromEstimateId?: number;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { DiscountType } from '@/common/types/Discount';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import {
|
||||
IsEnum,
|
||||
IsIn,
|
||||
@@ -11,66 +12,130 @@ import {
|
||||
|
||||
export class ItemEntryDto {
|
||||
@IsInt()
|
||||
@ApiProperty({
|
||||
description: 'The index of the item entry',
|
||||
example: 1,
|
||||
})
|
||||
index: number;
|
||||
|
||||
@IsInt()
|
||||
@IsNotEmpty()
|
||||
@ApiProperty({
|
||||
description: 'The id of the item',
|
||||
example: 1,
|
||||
})
|
||||
itemId: number;
|
||||
|
||||
@IsNumber()
|
||||
@IsNotEmpty()
|
||||
@ApiProperty({
|
||||
description: 'The rate of the item entry',
|
||||
example: 1,
|
||||
})
|
||||
rate: number;
|
||||
|
||||
@IsNumber()
|
||||
@IsNotEmpty()
|
||||
@ApiProperty({
|
||||
description: 'The quantity of the item entry',
|
||||
example: 1,
|
||||
})
|
||||
quantity: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
@ApiProperty({
|
||||
description: 'The discount of the item entry',
|
||||
example: 1,
|
||||
})
|
||||
discount?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsEnum(DiscountType)
|
||||
@ApiProperty({
|
||||
description: 'The type of the discount',
|
||||
example: DiscountType.Percentage,
|
||||
})
|
||||
discountType?: DiscountType = DiscountType.Percentage;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@ApiProperty({
|
||||
description: 'The description of the item entry',
|
||||
example: 'This is a description',
|
||||
})
|
||||
description?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@ApiProperty({
|
||||
description: 'The tax code of the item entry',
|
||||
example: '123456',
|
||||
})
|
||||
taxCode?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@ApiProperty({
|
||||
description: 'The tax rate id of the item entry',
|
||||
example: 1,
|
||||
})
|
||||
taxRateId?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@ApiProperty({
|
||||
description: 'The warehouse id of the item entry',
|
||||
example: 1,
|
||||
})
|
||||
warehouseId?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@ApiProperty({
|
||||
description: 'The project id of the item entry',
|
||||
example: 1,
|
||||
})
|
||||
projectId?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@ApiProperty({
|
||||
description: 'The project ref id of the item entry',
|
||||
example: 1,
|
||||
})
|
||||
projectRefId?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@IsIn(['TASK', 'BILL', 'EXPENSE'])
|
||||
@ApiProperty({
|
||||
description: 'The project ref type of the item entry',
|
||||
example: 'TASK',
|
||||
})
|
||||
projectRefType?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
@ApiProperty({
|
||||
description: 'The project ref invoiced amount of the item entry',
|
||||
example: 100,
|
||||
})
|
||||
projectRefInvoicedAmount?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@ApiProperty({
|
||||
description: 'The sell account id of the item entry',
|
||||
example: 1020,
|
||||
})
|
||||
sellAccountId?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@ApiProperty({
|
||||
description: 'The cost account id of the item entry',
|
||||
example: 1021,
|
||||
})
|
||||
costAccountId?: number;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ export class TransactionsLockingController {
|
||||
@ApiOperation({ summary: 'Partial unlock all transactions locking for a module or all modules' })
|
||||
async unlockTransactionsLockingBetweenPeriod(
|
||||
@Body('module') module: TransactionsLockingGroup,
|
||||
@Body() unlockDTO: UnlockTransactionsLockingDto,
|
||||
@Body() unlockDTO: ITransactionLockingPartiallyDTO,
|
||||
) {
|
||||
const transactionMeta =
|
||||
await this.transactionsLockingService.unlockTransactionsLockingPartially(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Knex } from 'knex';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import {
|
||||
IVendorCreditEditDTO,
|
||||
IVendorCreditEditedPayload,
|
||||
IVendorCreditEditingPayload,
|
||||
} from '../types/VendorCredit.types';
|
||||
@@ -10,7 +10,6 @@ import { ItemsEntriesService } from '@/modules/Items/ItemsEntries.service';
|
||||
import { VendorCredit } from '../models/VendorCredit';
|
||||
import { Contact } from '@/modules/Contacts/models/Contact';
|
||||
import { events } from '@/common/events/events';
|
||||
import { Knex } from 'knex';
|
||||
import { VendorCreditDTOTransformService } from './VendorCreditDTOTransform.service';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { EditVendorCreditDto } from '../dtos/VendorCredit.dto';
|
||||
@@ -40,7 +39,7 @@ export class EditVendorCreditService {
|
||||
/**
|
||||
* Deletes the given vendor credit.
|
||||
* @param {number} vendorCreditId - Vendor credit id.
|
||||
* @param {EditVendorCreditDto} vendorCreditDto -
|
||||
* @param {EditVendorCreditDto} vendorCreditDto -
|
||||
*/
|
||||
public editVendorCredit = async (
|
||||
vendorCreditId: number,
|
||||
|
||||
@@ -2,7 +2,6 @@ import * as moment from 'moment';
|
||||
import { omit } from 'lodash';
|
||||
import * as R from 'ramda';
|
||||
import { ERRORS } from '../constants';
|
||||
import { IVendorCreditEntryDTO } from '../types/VendorCredit.types';
|
||||
import { ItemsEntriesService } from '@/modules/Items/ItemsEntries.service';
|
||||
import { BranchTransactionDTOTransformer } from '@/modules/Branches/integrations/BranchTransactionDTOTransform';
|
||||
import { WarehouseTransactionDTOTransform } from '@/modules/Warehouses/Integrations/WarehouseTransactionDTOTransform';
|
||||
@@ -14,6 +13,7 @@ import { Injectable } from '@nestjs/common';
|
||||
import {
|
||||
CreateVendorCreditDto,
|
||||
EditVendorCreditDto,
|
||||
VendorCreditEntryDto,
|
||||
} from '../dtos/VendorCredit.dto';
|
||||
|
||||
@Injectable()
|
||||
@@ -52,7 +52,7 @@ export class VendorCreditDTOTransformService {
|
||||
assocItemEntriesDefaultIndex,
|
||||
|
||||
// Associate the reference type to item entries.
|
||||
R.map((entry: IVendorCreditEntryDTO) => ({
|
||||
R.map((entry: VendorCreditEntryDto) => ({
|
||||
referenceType: 'VendorCredit',
|
||||
...entry,
|
||||
})),
|
||||
|
||||
@@ -14,7 +14,7 @@ enum DiscountType {
|
||||
Amount = 'amount',
|
||||
}
|
||||
|
||||
class VendorCreditEntryDto extends ItemEntryDto {}
|
||||
export class VendorCreditEntryDto extends ItemEntryDto {}
|
||||
|
||||
class AttachmentDto {
|
||||
@IsString()
|
||||
|
||||
@@ -10,13 +10,13 @@ import {
|
||||
} from '@nestjs/common';
|
||||
import { VendorsApplication } from './VendorsApplication.service';
|
||||
import {
|
||||
IVendorEditDTO,
|
||||
IVendorNewDTO,
|
||||
IVendorOpeningBalanceEditDTO,
|
||||
IVendorsFilter,
|
||||
} from './types/Vendors.types';
|
||||
import { PublicRoute } from '../Auth/Jwt.guard';
|
||||
import { ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||
import { CreateVendorDto } from './dtos/CreateVendor.dto';
|
||||
import { EditVendorDto } from './dtos/EditVendor.dto';
|
||||
|
||||
@Controller('vendors')
|
||||
@ApiTags('vendors')
|
||||
@@ -38,13 +38,13 @@ export class VendorsController {
|
||||
|
||||
@Post()
|
||||
@ApiOperation({ summary: 'Create a new vendor.' })
|
||||
createVendor(@Body() vendorDTO: IVendorNewDTO) {
|
||||
createVendor(@Body() vendorDTO: CreateVendorDto) {
|
||||
return this.vendorsApplication.createVendor(vendorDTO);
|
||||
}
|
||||
|
||||
@Put(':id')
|
||||
@ApiOperation({ summary: 'Edit the given vendor.' })
|
||||
editVendor(@Param('id') vendorId: number, @Body() vendorDTO: IVendorEditDTO) {
|
||||
editVendor(@Param('id') vendorId: number, @Body() vendorDTO: EditVendorDto) {
|
||||
return this.vendorsApplication.editVendor(vendorId, vendorDTO);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,12 +6,12 @@ import { DeleteVendorService } from './commands/DeleteVendor.service';
|
||||
import { EditOpeningBalanceVendorService } from './commands/EditOpeningBalanceVendor.service';
|
||||
import { GetVendorService } from './queries/GetVendor';
|
||||
import {
|
||||
IVendorEditDTO,
|
||||
IVendorNewDTO,
|
||||
IVendorOpeningBalanceEditDTO,
|
||||
IVendorsFilter,
|
||||
} from './types/Vendors.types';
|
||||
import { GetVendorsService } from './queries/GetVendors.service';
|
||||
import { CreateVendorDto } from './dtos/CreateVendor.dto';
|
||||
import { EditVendorDto } from './dtos/EditVendor.dto';
|
||||
|
||||
@Injectable()
|
||||
export class VendorsApplication {
|
||||
@@ -29,7 +29,7 @@ export class VendorsApplication {
|
||||
* @param {IVendorNewDTO} vendorDTO
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
public createVendor(vendorDTO: IVendorNewDTO, trx?: Knex.Transaction) {
|
||||
public createVendor(vendorDTO: CreateVendorDto, trx?: Knex.Transaction) {
|
||||
return this.createVendorService.createVendor(vendorDTO, trx);
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ export class VendorsApplication {
|
||||
* @param {IVendorEditDTO} vendorDTO -
|
||||
* @returns {Promise<IVendor>}
|
||||
*/
|
||||
public editVendor(vendorId: number, vendorDTO: IVendorEditDTO) {
|
||||
public editVendor(vendorId: number, vendorDTO: EditVendorDto) {
|
||||
return this.editVendorService.editVendor(vendorId, vendorDTO);
|
||||
}
|
||||
|
||||
@@ -84,5 +84,5 @@ export class VendorsApplication {
|
||||
*/
|
||||
public getVendors(filterDTO: IVendorsFilter) {
|
||||
return this.getVendorsService.getVendorsList(filterDTO);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { IVendorEditDTO, IVendorNewDTO } from '../types/Vendors.types';
|
||||
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
|
||||
import { ContactService } from '@/modules/Contacts/types/Contacts.types';
|
||||
import { Vendor } from '../models/Vendor';
|
||||
import { CreateVendorDto } from '../dtos/CreateVendor.dto';
|
||||
|
||||
@Injectable()
|
||||
export class CreateEditVendorDTOService {
|
||||
@@ -30,7 +31,7 @@ export class CreateEditVendorDTOService {
|
||||
* @returns {IVendorNewDTO}
|
||||
*/
|
||||
public transformCreateDTO = async (
|
||||
vendorDTO: IVendorNewDTO,
|
||||
vendorDTO: CreateVendorDto,
|
||||
): Promise<Partial<Vendor>> => {
|
||||
const commonDTO = this.transformCommonDTO(vendorDTO);
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
} from '../types/Vendors.types';
|
||||
import { CreateEditVendorDTOService } from './CreateEditVendorDTO';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { CreateVendorDto } from '../dtos/CreateVendor.dto';
|
||||
|
||||
@Injectable()
|
||||
export class CreateVendorService {
|
||||
@@ -34,7 +35,7 @@ export class CreateVendorService {
|
||||
* @param {IVendorNewDTO} vendorDTO
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
public async createVendor(vendorDTO: IVendorNewDTO, trx?: Knex.Transaction) {
|
||||
public async createVendor(vendorDTO: CreateVendorDto, trx?: Knex.Transaction) {
|
||||
// Transforms create DTO to customer object.
|
||||
const vendorObject = await this.transformDTO.transformCreateDTO(vendorDTO);
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {
|
||||
IVendorEditDTO,
|
||||
IVendorEventEditedPayload,
|
||||
IVendorEventEditingPayload,
|
||||
} from '../types/Vendors.types';
|
||||
@@ -11,6 +10,7 @@ import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { Vendor } from '../models/Vendor';
|
||||
import { events } from '@/common/events/events';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { EditVendorDto } from '../dtos/EditVendor.dto';
|
||||
|
||||
@Injectable()
|
||||
export class EditVendorService {
|
||||
@@ -29,7 +29,7 @@ export class EditVendorService {
|
||||
* @param {IVendorEditDTO} vendorDTO -
|
||||
* @returns {Promise<IVendor>}
|
||||
*/
|
||||
public async editVendor(vendorId: number, vendorDTO: IVendorEditDTO) {
|
||||
public async editVendor(vendorId: number, vendorDTO: EditVendorDto) {
|
||||
// Retrieve the vendor or throw not found error.
|
||||
const oldVendor = await this.vendorModel()
|
||||
.query()
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsBoolean, IsEmail, IsString } from 'class-validator';
|
||||
import { ContactAddressDto } from '@/modules/Customers/dtos/ContactAddress.dto';
|
||||
import { IsInt, IsNumber } from 'class-validator';
|
||||
import { IsOptional, Min } from 'class-validator';
|
||||
import { IsISO8601 } from 'class-validator';
|
||||
|
||||
export class CreateVendorDto extends ContactAddressDto {
|
||||
@ApiProperty({ required: false, description: 'Vendor opening balance' })
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@Min(0)
|
||||
openingBalance?: number;
|
||||
|
||||
@ApiProperty({
|
||||
required: false,
|
||||
description: 'Vendor opening balance exchange rate',
|
||||
default: 1,
|
||||
})
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
@Min(0.01)
|
||||
openingBalanceExchangeRate?: number;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Date of the opening balance' })
|
||||
@IsOptional()
|
||||
@IsISO8601()
|
||||
openingBalanceAt?: Date;
|
||||
|
||||
@ApiProperty({
|
||||
required: false,
|
||||
description: 'Branch ID for the opening balance',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
openingBalanceBranchId?: number;
|
||||
|
||||
@ApiProperty({ description: 'Currency code for the vendor' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
currencyCode: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Vendor salutation' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
salutation?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Vendor first name' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
firstName?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Vendor last name' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
lastName?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Vendor company name' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
companyName?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Vendor display name' })
|
||||
@IsString()
|
||||
displayName: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Vendor website' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
website?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Vendor email address' })
|
||||
@IsOptional()
|
||||
@IsEmail()
|
||||
email?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Vendor work phone number' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
workPhone?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Vendor personal phone number' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
personalPhone?: string;
|
||||
|
||||
@ApiProperty({
|
||||
required: false,
|
||||
description: 'Additional notes about the vendor',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
note?: string;
|
||||
|
||||
@ApiProperty({
|
||||
required: false,
|
||||
description: 'Whether the vendor is active',
|
||||
default: true,
|
||||
})
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
active?: boolean;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import { ContactAddressDto } from '@/modules/Customers/dtos/ContactAddress.dto';
|
||||
import { IsEmail, IsString, IsBoolean, IsOptional } from 'class-validator';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
export class EditVendorDto extends ContactAddressDto {
|
||||
@ApiProperty({ required: false, description: 'Vendor salutation' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
salutation?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Vendor first name' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
firstName?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Vendor last name' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
lastName?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Vendor company name' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
companyName?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Vendor display name' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
displayName?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Vendor website' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
website?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Vendor email address' })
|
||||
@IsOptional()
|
||||
@IsEmail()
|
||||
email?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Vendor work phone number' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
workPhone?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Vendor personal phone number' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
personalPhone?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Additional notes about the vendor' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
note?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Whether the vendor is active' })
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
active?: boolean;
|
||||
}
|
||||
@@ -5,6 +5,8 @@ import { Vendor } from '../models/Vendor';
|
||||
import { IContactAddressDTO } from '@/modules/Contacts/types/Contacts.types';
|
||||
import { IDynamicListFilter } from '@/modules/DynamicListing/DynamicFilter/DynamicFilter.types';
|
||||
import { IFilterMeta, IPaginationMeta } from '@/interfaces/Model';
|
||||
import { CreateVendorDto } from '../dtos/CreateVendor.dto';
|
||||
import { EditVendorDto } from '../dtos/EditVendor.dto';
|
||||
|
||||
// ----------------------------------
|
||||
export interface IVendorNewDTO extends IContactAddressDTO {
|
||||
@@ -60,43 +62,33 @@ export interface GetVendorsResponse {
|
||||
// Vendor Events.
|
||||
// ----------------------------------
|
||||
export interface IVendorEventCreatingPayload {
|
||||
// tenantId: number;
|
||||
vendorDTO: IVendorNewDTO;
|
||||
// authorizedUser: ISystemUser;
|
||||
vendorDTO: CreateVendorDto;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface IVendorEventCreatedPayload {
|
||||
// tenantId: number;
|
||||
vendorId: number;
|
||||
vendor: Vendor;
|
||||
// authorizedUser: ISystemUser;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface IVendorEventDeletingPayload {
|
||||
// tenantId: number;
|
||||
vendorId: number;
|
||||
oldVendor: Vendor;
|
||||
}
|
||||
|
||||
export interface IVendorEventDeletedPayload {
|
||||
// tenantId: number;
|
||||
vendorId: number;
|
||||
// authorizedUser: ISystemUser;
|
||||
oldVendor: Vendor;
|
||||
trx?: Knex.Transaction;
|
||||
}
|
||||
export interface IVendorEventEditingPayload {
|
||||
// tenantId: number;
|
||||
vendorDTO: IVendorEditDTO;
|
||||
vendorDTO: EditVendorDto;
|
||||
trx?: Knex.Transaction;
|
||||
}
|
||||
export interface IVendorEventEditedPayload {
|
||||
// tenantId: number;
|
||||
vendorId: number;
|
||||
vendor: Vendor;
|
||||
// authorizedUser: ISystemUser;
|
||||
trx?: Knex.Transaction;
|
||||
}
|
||||
|
||||
@@ -108,14 +100,12 @@ export interface IVendorOpeningBalanceEditDTO {
|
||||
}
|
||||
|
||||
export interface IVendorOpeningBalanceEditingPayload {
|
||||
// tenantId: number;
|
||||
oldVendor: Vendor;
|
||||
openingBalanceEditDTO: IVendorOpeningBalanceEditDTO;
|
||||
trx?: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface IVendorOpeningBalanceEditedPayload {
|
||||
// tenantId: number;
|
||||
vendor: Vendor;
|
||||
oldVendor: Vendor;
|
||||
openingBalanceEditDTO: IVendorOpeningBalanceEditDTO;
|
||||
@@ -123,13 +113,11 @@ export interface IVendorOpeningBalanceEditedPayload {
|
||||
}
|
||||
|
||||
export interface IVendorActivatingPayload {
|
||||
// tenantId: number;
|
||||
oldVendor: Vendor;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface IVendorActivatedPayload {
|
||||
// tenantId: number;
|
||||
vendor: Vendor;
|
||||
oldVendor: Vendor;
|
||||
trx?: Knex.Transaction;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { Type } from 'class-transformer';
|
||||
import {
|
||||
IsArray,
|
||||
@@ -39,32 +40,68 @@ export class WarehouseTransferEntryDto {
|
||||
export class CommandWarehouseTransferDto {
|
||||
@IsNotEmpty()
|
||||
@IsInt()
|
||||
@ApiProperty({
|
||||
description: 'The id of the warehouse to transfer from',
|
||||
example: 1,
|
||||
})
|
||||
fromWarehouseId: number;
|
||||
|
||||
@IsNotEmpty()
|
||||
@IsInt()
|
||||
@ApiProperty({
|
||||
description: 'The id of the warehouse to transfer to',
|
||||
example: 2,
|
||||
})
|
||||
toWarehouseId: number;
|
||||
|
||||
@IsNotEmpty()
|
||||
@IsDate()
|
||||
@ApiProperty({
|
||||
description: 'The date of the warehouse transfer',
|
||||
example: '2021-01-01',
|
||||
})
|
||||
date: Date;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@ApiProperty({
|
||||
description: 'The transaction number of the warehouse transfer',
|
||||
example: '123456',
|
||||
})
|
||||
transactionNumber?: string;
|
||||
|
||||
@IsBoolean()
|
||||
@IsOptional()
|
||||
@ApiProperty({
|
||||
description: 'Whether the warehouse transfer has been initiated',
|
||||
example: false,
|
||||
})
|
||||
transferInitiated: boolean = false;
|
||||
|
||||
@IsBoolean()
|
||||
@IsOptional()
|
||||
@ApiProperty({
|
||||
description: 'Whether the warehouse transfer has been delivered',
|
||||
example: false,
|
||||
})
|
||||
transferDelivered: boolean = false;
|
||||
|
||||
@IsArray()
|
||||
@ArrayMinSize(1)
|
||||
@ValidateNested({ each: true })
|
||||
@Type(() => WarehouseTransferEntryDto)
|
||||
@ApiProperty({
|
||||
description: 'The entries of the warehouse transfer',
|
||||
example: [
|
||||
{
|
||||
index: 1,
|
||||
itemId: 1,
|
||||
description: 'This is a description',
|
||||
quantity: 100,
|
||||
cost: 100,
|
||||
},
|
||||
],
|
||||
})
|
||||
entries: WarehouseTransferEntryDto[];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user