chore: format all packages
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { registerAs } from "@nestjs/config";
|
import { registerAs } from '@nestjs/config';
|
||||||
|
|
||||||
export default registerAs('inventory', () => ({
|
export default registerAs('inventory', () => ({
|
||||||
scheduleComputeItemCost: process.env.INVENTORY_SCHEDULE_COMPUTE_ITEM_COST,
|
scheduleComputeItemCost: process.env.INVENTORY_SCHEDULE_COMPUTE_ITEM_COST,
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import { registerAs } from '@nestjs/config';
|
import { registerAs } from '@nestjs/config';
|
||||||
|
|
||||||
export default registerAs('loops', () => ({
|
export default registerAs('loops', () => ({
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ export default registerAs('systemDatabase', () => ({
|
|||||||
user: process.env.SYSTEM_DB_USER || process.env.DB_USER,
|
user: process.env.SYSTEM_DB_USER || process.env.DB_USER,
|
||||||
password: process.env.SYSTEM_DB_PASSWORD || process.env.DB_PASSWORD,
|
password: process.env.SYSTEM_DB_PASSWORD || process.env.DB_PASSWORD,
|
||||||
databaseName: process.env.SYSTEM_DB_NAME || process.env.DB_NAME,
|
databaseName: process.env.SYSTEM_DB_NAME || process.env.DB_NAME,
|
||||||
migrationDir: process.env.SYSTEM_DB_MIGRATION_DIR || './src/database/system/migrations',
|
migrationDir:
|
||||||
|
process.env.SYSTEM_DB_MIGRATION_DIR || './src/database/system/migrations',
|
||||||
seedsDir: process.env.SYSTEM_DB_SEEDS_DIR || './src/database/system/seeds',
|
seedsDir: process.env.SYSTEM_DB_SEEDS_DIR || './src/database/system/seeds',
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -10,5 +10,3 @@ export default registerAs('throttle', () => ({
|
|||||||
limit: parseInt(process.env.THROTTLE_AUTH_LIMIT ?? '10', 10),
|
limit: parseInt(process.env.THROTTLE_AUTH_LIMIT ?? '10', 10),
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export const MULTER_MODULE_OPTIONS = 'MULTER_MODULE_OPTIONS';
|
export const MULTER_MODULE_OPTIONS = 'MULTER_MODULE_OPTIONS';
|
||||||
|
|||||||
@@ -5,4 +5,4 @@ export const ACCEPT_TYPE = {
|
|||||||
APPLICATION_XLSX: 'application/xlsx',
|
APPLICATION_XLSX: 'application/xlsx',
|
||||||
APPLICATION_CSV: 'application/csv',
|
APPLICATION_CSV: 'application/csv',
|
||||||
APPLICATION_TEXT_HTML: 'application/json+html',
|
APPLICATION_TEXT_HTML: 'application/json+html',
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,5 +20,3 @@ export const busboyExceptions = {
|
|||||||
MULTIPART_UNEXPECTED_END_OF_FORM: 'Unexpected end of form',
|
MULTIPART_UNEXPECTED_END_OF_FORM: 'Unexpected end of form',
|
||||||
MULTIPART_UNEXPECTED_END_OF_FILE: 'Unexpected end of file',
|
MULTIPART_UNEXPECTED_END_OF_FILE: 'Unexpected end of file',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -35,4 +35,4 @@ export function transformException(
|
|||||||
return new BadRequestException(`Multipart: ${error.message}`);
|
return new BadRequestException(`Multipart: ${error.message}`);
|
||||||
}
|
}
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
import { IsArray, IsInt, ArrayNotEmpty, IsBoolean, IsOptional } from 'class-validator';
|
import {
|
||||||
|
IsArray,
|
||||||
|
IsInt,
|
||||||
|
ArrayNotEmpty,
|
||||||
|
IsBoolean,
|
||||||
|
IsOptional,
|
||||||
|
} from 'class-validator';
|
||||||
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||||||
import { Transform } from 'class-transformer';
|
import { Transform } from 'class-transformer';
|
||||||
import { parseBoolean } from '@/utils/parse-boolean';
|
import { parseBoolean } from '@/utils/parse-boolean';
|
||||||
@@ -16,9 +22,12 @@ export class BulkDeleteDto {
|
|||||||
|
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
@Transform(({ value, obj }) => parseBoolean(value ?? obj?.skip_undeletable, false))
|
@Transform(({ value, obj }) =>
|
||||||
|
parseBoolean(value ?? obj?.skip_undeletable, false),
|
||||||
|
)
|
||||||
@ApiPropertyOptional({
|
@ApiPropertyOptional({
|
||||||
description: 'When true, undeletable items will be skipped and only deletable ones will be removed.',
|
description:
|
||||||
|
'When true, undeletable items will be skipped and only deletable ones will be removed.',
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
@@ -52,4 +61,3 @@ export class ValidateBulkDeleteResponseDto {
|
|||||||
})
|
})
|
||||||
nonDeletableIds: number[];
|
nonDeletableIds: number[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ export class ServiceErrorFilter implements ExceptionFilter {
|
|||||||
type: exception.errorType,
|
type: exception.errorType,
|
||||||
message: exception.message,
|
message: exception.message,
|
||||||
payload: exception.payload,
|
payload: exception.payload,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,12 +29,11 @@ export function FileInterceptor(
|
|||||||
constructor(
|
constructor(
|
||||||
@Optional()
|
@Optional()
|
||||||
@Inject(MULTER_MODULE_OPTIONS)
|
@Inject(MULTER_MODULE_OPTIONS)
|
||||||
options: (() => MulterModuleOptions | MulterModuleOptions) = () => ({}),
|
options: () => MulterModuleOptions | MulterModuleOptions = () => ({}),
|
||||||
) {
|
) {
|
||||||
const resolvedOptions = typeof localOptions === 'function'
|
const resolvedOptions =
|
||||||
? localOptions(this)
|
typeof localOptions === 'function' ? localOptions(this) : localOptions;
|
||||||
: localOptions;
|
|
||||||
|
|
||||||
this.multer = (multer as any)({
|
this.multer = (multer as any)({
|
||||||
...(typeof options === 'function' ? options() : options),
|
...(typeof options === 'function' ? options() : options),
|
||||||
...resolvedOptions,
|
...resolvedOptions,
|
||||||
@@ -67,4 +66,4 @@ export function FileInterceptor(
|
|||||||
const Interceptor = mixin(MixinInterceptor);
|
const Interceptor = mixin(MixinInterceptor);
|
||||||
|
|
||||||
return Interceptor;
|
return Interceptor;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export const DEFAULT_STRATEGY = {
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SerializeInterceptor implements NestInterceptor<any, any> {
|
export class SerializeInterceptor implements NestInterceptor<any, any> {
|
||||||
constructor(@Optional() readonly strategy = DEFAULT_STRATEGY) { }
|
constructor(@Optional() readonly strategy = DEFAULT_STRATEGY) {}
|
||||||
|
|
||||||
intercept(
|
intercept(
|
||||||
context: ExecutionContext,
|
context: ExecutionContext,
|
||||||
|
|||||||
@@ -16,7 +16,11 @@ export class ToJsonInterceptor implements NestInterceptor {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
return mapValuesDeep(data, (value) => {
|
return mapValuesDeep(data, (value) => {
|
||||||
if (value !== null && value !== undefined && typeof value.toJSON === 'function') {
|
if (
|
||||||
|
value !== null &&
|
||||||
|
value !== undefined &&
|
||||||
|
typeof value.toJSON === 'function'
|
||||||
|
) {
|
||||||
return value.toJSON();
|
return value.toJSON();
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
// import { CachableRepository } from './CachableRepository';
|
// import { CachableRepository } from './CachableRepository';
|
||||||
import { EntityRepository } from './EntityRepository';
|
import { EntityRepository } from './EntityRepository';
|
||||||
|
|
||||||
export class TenantRepository extends EntityRepository {
|
export class TenantRepository extends EntityRepository {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
import * as moment from 'moment';
|
import * as moment from 'moment';
|
||||||
|
|
||||||
export type DateInput = moment.MomentInput;
|
export type DateInput = moment.MomentInput;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export enum DiscountType {
|
export enum DiscountType {
|
||||||
Percentage = 'percentage',
|
Percentage = 'percentage',
|
||||||
Amount = 'amount',
|
Amount = 'amount',
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-15
@@ -1,19 +1,25 @@
|
|||||||
exports.up = function (knex) {
|
exports.up = function (knex) {
|
||||||
return knex.schema.createTable('accounts', (table) => {
|
return knex.schema
|
||||||
table.increments('id').comment('Auto-generated id');
|
.createTable('accounts', (table) => {
|
||||||
table.string('name').index();
|
table.increments('id').comment('Auto-generated id');
|
||||||
table.string('slug');
|
table.string('name').index();
|
||||||
table.string('account_type').index();
|
table.string('slug');
|
||||||
table.integer('parent_account_id').unsigned().references('id').inTable('accounts');
|
table.string('account_type').index();
|
||||||
table.string('code', 10).index();
|
table
|
||||||
table.text('description');
|
.integer('parent_account_id')
|
||||||
table.boolean('active').defaultTo(true).index();
|
.unsigned()
|
||||||
table.integer('index').unsigned();
|
.references('id')
|
||||||
table.boolean('predefined').defaultTo(false).index();
|
.inTable('accounts');
|
||||||
table.decimal('amount', 15, 5);
|
table.string('code', 10).index();
|
||||||
table.string('currency_code', 3).index();
|
table.text('description');
|
||||||
table.timestamps();
|
table.boolean('active').defaultTo(true).index();
|
||||||
}).raw('ALTER TABLE `ACCOUNTS` AUTO_INCREMENT = 1000');
|
table.integer('index').unsigned();
|
||||||
|
table.boolean('predefined').defaultTo(false).index();
|
||||||
|
table.decimal('amount', 15, 5);
|
||||||
|
table.string('currency_code', 3).index();
|
||||||
|
table.timestamps();
|
||||||
|
})
|
||||||
|
.raw('ALTER TABLE `ACCOUNTS` AUTO_INCREMENT = 1000');
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.down = (knex) => knex.schema.dropTableIfExists('accounts');
|
exports.down = (knex) => knex.schema.dropTableIfExists('accounts');
|
||||||
|
|||||||
+16
-5
@@ -1,15 +1,26 @@
|
|||||||
|
|
||||||
exports.up = function (knex) {
|
exports.up = function (knex) {
|
||||||
return knex.schema.createTable('items_categories', (table) => {
|
return knex.schema.createTable('items_categories', (table) => {
|
||||||
table.increments();
|
table.increments();
|
||||||
table.string('name').index();
|
table.string('name').index();
|
||||||
|
|
||||||
table.text('description');
|
table.text('description');
|
||||||
table.integer('user_id').unsigned().index();
|
table.integer('user_id').unsigned().index();
|
||||||
|
|
||||||
table.integer('cost_account_id').unsigned().references('id').inTable('accounts');
|
table
|
||||||
table.integer('sell_account_id').unsigned().references('id').inTable('accounts');
|
.integer('cost_account_id')
|
||||||
table.integer('inventory_account_id').unsigned().references('id').inTable('accounts');
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('accounts');
|
||||||
|
table
|
||||||
|
.integer('sell_account_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('accounts');
|
||||||
|
table
|
||||||
|
.integer('inventory_account_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('accounts');
|
||||||
|
|
||||||
table.string('cost_method');
|
table.string('cost_method');
|
||||||
table.timestamps();
|
table.timestamps();
|
||||||
|
|||||||
+45
-25
@@ -1,30 +1,50 @@
|
|||||||
|
|
||||||
exports.up = function (knex) {
|
exports.up = function (knex) {
|
||||||
return knex.schema.createTable('items', (table) => {
|
return knex.schema
|
||||||
table.increments();
|
.createTable('items', (table) => {
|
||||||
table.string('name').index();
|
table.increments();
|
||||||
table.string('type').index();
|
table.string('name').index();
|
||||||
table.string('code');
|
table.string('type').index();
|
||||||
table.boolean('sellable').index();
|
table.string('code');
|
||||||
table.boolean('purchasable').index();
|
table.boolean('sellable').index();
|
||||||
table.decimal('sell_price', 13, 3).unsigned();
|
table.boolean('purchasable').index();
|
||||||
table.decimal('cost_price', 13, 3).unsigned();
|
table.decimal('sell_price', 13, 3).unsigned();
|
||||||
table.string('currency_code', 3);
|
table.decimal('cost_price', 13, 3).unsigned();
|
||||||
table.string('picture_uri');
|
table.string('currency_code', 3);
|
||||||
table.integer('cost_account_id').nullable().unsigned().references('id').inTable('accounts');
|
table.string('picture_uri');
|
||||||
table.integer('sell_account_id').nullable().unsigned().references('id').inTable('accounts');
|
table
|
||||||
table.integer('inventory_account_id').unsigned().references('id').inTable('accounts');
|
.integer('cost_account_id')
|
||||||
table.text('sell_description').nullable();
|
.nullable()
|
||||||
table.text('purchase_description').nullable();
|
.unsigned()
|
||||||
table.integer('quantity_on_hand');
|
.references('id')
|
||||||
table.boolean('landed_cost').nullable();
|
.inTable('accounts');
|
||||||
|
table
|
||||||
|
.integer('sell_account_id')
|
||||||
|
.nullable()
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('accounts');
|
||||||
|
table
|
||||||
|
.integer('inventory_account_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('accounts');
|
||||||
|
table.text('sell_description').nullable();
|
||||||
|
table.text('purchase_description').nullable();
|
||||||
|
table.integer('quantity_on_hand');
|
||||||
|
table.boolean('landed_cost').nullable();
|
||||||
|
|
||||||
table.text('note').nullable();
|
table.text('note').nullable();
|
||||||
table.boolean('active');
|
table.boolean('active');
|
||||||
table.integer('category_id').unsigned().index().references('id').inTable('items_categories');
|
table
|
||||||
table.integer('user_id').unsigned().index();
|
.integer('category_id')
|
||||||
table.timestamps();
|
.unsigned()
|
||||||
}).raw('ALTER TABLE `ITEMS` AUTO_INCREMENT = 1000');
|
.index()
|
||||||
|
.references('id')
|
||||||
|
.inTable('items_categories');
|
||||||
|
table.integer('user_id').unsigned().index();
|
||||||
|
table.timestamps();
|
||||||
|
})
|
||||||
|
.raw('ALTER TABLE `ITEMS` AUTO_INCREMENT = 1000');
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.down = (knex) => knex.schema.dropTableIfExists('items');
|
exports.down = (knex) => knex.schema.dropTableIfExists('items');
|
||||||
|
|||||||
+12
-11
@@ -1,15 +1,16 @@
|
|||||||
|
|
||||||
exports.up = function (knex) {
|
exports.up = function (knex) {
|
||||||
return knex.schema.createTable('views', (table) => {
|
return knex.schema
|
||||||
table.increments();
|
.createTable('views', (table) => {
|
||||||
table.string('name').index();
|
table.increments();
|
||||||
table.string('slug').index();
|
table.string('name').index();
|
||||||
table.boolean('predefined');
|
table.string('slug').index();
|
||||||
table.string('resource_model').index();
|
table.boolean('predefined');
|
||||||
table.boolean('favourite');
|
table.string('resource_model').index();
|
||||||
table.string('roles_logic_expression');
|
table.boolean('favourite');
|
||||||
table.timestamps();
|
table.string('roles_logic_expression');
|
||||||
}).raw('ALTER TABLE `VIEWS` AUTO_INCREMENT = 1000');
|
table.timestamps();
|
||||||
|
})
|
||||||
|
.raw('ALTER TABLE `VIEWS` AUTO_INCREMENT = 1000');
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.down = (knex) => knex.schema.dropTableIfExists('views');
|
exports.down = (knex) => knex.schema.dropTableIfExists('views');
|
||||||
|
|||||||
+10
-9
@@ -1,13 +1,14 @@
|
|||||||
|
|
||||||
exports.up = function (knex) {
|
exports.up = function (knex) {
|
||||||
return knex.schema.createTable('settings', (table) => {
|
return knex.schema
|
||||||
table.increments();
|
.createTable('settings', (table) => {
|
||||||
table.integer('user_id').unsigned().index();
|
table.increments();
|
||||||
table.string('group').index();
|
table.integer('user_id').unsigned().index();
|
||||||
table.string('type');
|
table.string('group').index();
|
||||||
table.string('key').index();
|
table.string('type');
|
||||||
table.string('value');
|
table.string('key').index();
|
||||||
}).raw('ALTER TABLE `SETTINGS` AUTO_INCREMENT = 2000');
|
table.string('value');
|
||||||
|
})
|
||||||
|
.raw('ALTER TABLE `SETTINGS` AUTO_INCREMENT = 2000');
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.down = (knex) => knex.schema.dropTableIfExists('settings');
|
exports.down = (knex) => knex.schema.dropTableIfExists('settings');
|
||||||
|
|||||||
+13
-7
@@ -1,11 +1,17 @@
|
|||||||
|
|
||||||
exports.up = function (knex) {
|
exports.up = function (knex) {
|
||||||
return knex.schema.createTable('view_has_columns', (table) => {
|
return knex.schema
|
||||||
table.increments();
|
.createTable('view_has_columns', (table) => {
|
||||||
table.integer('view_id').unsigned().index().references('id').inTable('views');
|
table.increments();
|
||||||
table.string('field_key');
|
table
|
||||||
table.integer('index').unsigned();
|
.integer('view_id')
|
||||||
}).raw('ALTER TABLE `ITEMS_CATEGORIES` AUTO_INCREMENT = 1000');
|
.unsigned()
|
||||||
|
.index()
|
||||||
|
.references('id')
|
||||||
|
.inTable('views');
|
||||||
|
table.string('field_key');
|
||||||
|
table.integer('index').unsigned();
|
||||||
|
})
|
||||||
|
.raw('ALTER TABLE `ITEMS_CATEGORIES` AUTO_INCREMENT = 1000');
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.down = (knex) => knex.schema.dropTableIfExists('view_has_columns');
|
exports.down = (knex) => knex.schema.dropTableIfExists('view_has_columns');
|
||||||
|
|||||||
+4
-6
@@ -1,6 +1,5 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
exports.up = function(knex) {
|
return knex.schema.createTable('contacts', (table) => {
|
||||||
return knex.schema.createTable('contacts', table => {
|
|
||||||
table.increments();
|
table.increments();
|
||||||
|
|
||||||
table.string('contact_service');
|
table.string('contact_service');
|
||||||
@@ -32,8 +31,7 @@ exports.up = function(knex) {
|
|||||||
table.string('billing_address_postcode').nullable();
|
table.string('billing_address_postcode').nullable();
|
||||||
table.string('billing_address_phone').nullable();
|
table.string('billing_address_phone').nullable();
|
||||||
table.string('billing_address_state').nullable(),
|
table.string('billing_address_state').nullable(),
|
||||||
|
table.string('shipping_address_1').nullable();
|
||||||
table.string('shipping_address_1').nullable();
|
|
||||||
table.string('shipping_address_2').nullable();
|
table.string('shipping_address_2').nullable();
|
||||||
table.string('shipping_address_city').nullable();
|
table.string('shipping_address_city').nullable();
|
||||||
table.string('shipping_address_country').nullable();
|
table.string('shipping_address_country').nullable();
|
||||||
@@ -49,6 +47,6 @@ exports.up = function(knex) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.down = function(knex) {
|
exports.down = function (knex) {
|
||||||
return knex.schema.dropTableIfExists('contacts');
|
return knex.schema.dropTableIfExists('contacts');
|
||||||
};
|
};
|
||||||
|
|||||||
+18
-17
@@ -1,21 +1,22 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
exports.up = function(knex) {
|
return knex.schema
|
||||||
return knex.schema.createTable('manual_journals', (table) => {
|
.createTable('manual_journals', (table) => {
|
||||||
table.increments();
|
table.increments();
|
||||||
table.string('journal_number').index();
|
table.string('journal_number').index();
|
||||||
table.string('reference').index();
|
table.string('reference').index();
|
||||||
table.string('journal_type').index();
|
table.string('journal_type').index();
|
||||||
table.decimal('amount', 13, 3);
|
table.decimal('amount', 13, 3);
|
||||||
table.string('currency_code', 3);
|
table.string('currency_code', 3);
|
||||||
table.date('date').index();
|
table.date('date').index();
|
||||||
table.string('description');
|
table.string('description');
|
||||||
table.date('published_at').index();
|
table.date('published_at').index();
|
||||||
table.string('attachment_file');
|
table.string('attachment_file');
|
||||||
table.integer('user_id').unsigned().index();
|
table.integer('user_id').unsigned().index();
|
||||||
table.timestamps();
|
table.timestamps();
|
||||||
}).raw('ALTER TABLE `MANUAL_JOURNALS` AUTO_INCREMENT = 1000');
|
})
|
||||||
|
.raw('ALTER TABLE `MANUAL_JOURNALS` AUTO_INCREMENT = 1000');
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.down = function(knex) {
|
exports.down = function (knex) {
|
||||||
return knex.schema.dropTableIfExists('manual_journals');
|
return knex.schema.dropTableIfExists('manual_journals');
|
||||||
};
|
};
|
||||||
|
|||||||
+24
-13
@@ -1,17 +1,28 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
exports.up = function(knex) {
|
return knex.schema
|
||||||
return knex.schema.createTable('manual_journals_entries', (table) => {
|
.createTable('manual_journals_entries', (table) => {
|
||||||
table.increments();
|
table.increments();
|
||||||
table.decimal('credit', 13, 3);
|
table.decimal('credit', 13, 3);
|
||||||
table.decimal('debit', 13, 3);
|
table.decimal('debit', 13, 3);
|
||||||
table.integer('index').unsigned();
|
table.integer('index').unsigned();
|
||||||
table.integer('account_id').unsigned().index().references('id').inTable('accounts');
|
table
|
||||||
table.integer('contact_id').unsigned().nullable().index();
|
.integer('account_id')
|
||||||
table.string('note');
|
.unsigned()
|
||||||
table.integer('manual_journal_id').unsigned().index().references('id').inTable('manual_journals');
|
.index()
|
||||||
}).raw('ALTER TABLE `MANUAL_JOURNALS_ENTRIES` AUTO_INCREMENT = 1000');
|
.references('id')
|
||||||
|
.inTable('accounts');
|
||||||
|
table.integer('contact_id').unsigned().nullable().index();
|
||||||
|
table.string('note');
|
||||||
|
table
|
||||||
|
.integer('manual_journal_id')
|
||||||
|
.unsigned()
|
||||||
|
.index()
|
||||||
|
.references('id')
|
||||||
|
.inTable('manual_journals');
|
||||||
|
})
|
||||||
|
.raw('ALTER TABLE `MANUAL_JOURNALS_ENTRIES` AUTO_INCREMENT = 1000');
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.down = function(knex) {
|
exports.down = function (knex) {
|
||||||
return knex.schema.dropTableIfExists('manual_journals_entries');
|
return knex.schema.dropTableIfExists('manual_journals_entries');
|
||||||
};
|
};
|
||||||
|
|||||||
+11
-10
@@ -1,14 +1,15 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
exports.up = function(knex) {
|
return knex.schema
|
||||||
return knex.schema.createTable('currencies', table => {
|
.createTable('currencies', (table) => {
|
||||||
table.increments();
|
table.increments();
|
||||||
table.string('currency_name').index();
|
table.string('currency_name').index();
|
||||||
table.string('currency_code', 4).index();
|
table.string('currency_code', 4).index();
|
||||||
table.string('currency_sign').index();
|
table.string('currency_sign').index();
|
||||||
table.timestamps();
|
table.timestamps();
|
||||||
}).raw('ALTER TABLE `CURRENCIES` AUTO_INCREMENT = 1000');
|
})
|
||||||
|
.raw('ALTER TABLE `CURRENCIES` AUTO_INCREMENT = 1000');
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.down = function(knex) {
|
exports.down = function (knex) {
|
||||||
return knex.schema.dropTableIfExists('currencies');
|
return knex.schema.dropTableIfExists('currencies');
|
||||||
};
|
};
|
||||||
|
|||||||
+11
-10
@@ -1,14 +1,15 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
exports.up = function(knex) {
|
return knex.schema
|
||||||
return knex.schema.createTable('exchange_rates', table => {
|
.createTable('exchange_rates', (table) => {
|
||||||
table.increments();
|
table.increments();
|
||||||
table.string('currency_code', 4).index();
|
table.string('currency_code', 4).index();
|
||||||
table.decimal('exchange_rate');
|
table.decimal('exchange_rate');
|
||||||
table.date('date').index();
|
table.date('date').index();
|
||||||
table.timestamps();
|
table.timestamps();
|
||||||
}).raw('ALTER TABLE `EXCHANGE_RATES` AUTO_INCREMENT = 1000');
|
})
|
||||||
|
.raw('ALTER TABLE `EXCHANGE_RATES` AUTO_INCREMENT = 1000');
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.down = function(knex) {
|
exports.down = function (knex) {
|
||||||
return knex.schema.dropTableIfExists('exchange_rates');
|
return knex.schema.dropTableIfExists('exchange_rates');
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
exports.up = function(knex) {
|
|
||||||
return knex.schema.createTable('media', (table) => {
|
return knex.schema.createTable('media', (table) => {
|
||||||
table.increments();
|
table.increments();
|
||||||
table.string('attachment_file');
|
table.string('attachment_file');
|
||||||
table.timestamps();
|
table.timestamps();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.down = function(knex) {
|
exports.down = function (knex) {
|
||||||
return knex.schema.dropTableIfExists('media');
|
return knex.schema.dropTableIfExists('media');
|
||||||
};
|
};
|
||||||
|
|||||||
+4
-5
@@ -1,13 +1,12 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
exports.up = function(knex) {
|
return knex.schema.createTable('media_links', (table) => {
|
||||||
return knex.schema.createTable('media_links', table => {
|
|
||||||
table.increments();
|
table.increments();
|
||||||
table.string('model_name').index();
|
table.string('model_name').index();
|
||||||
table.integer('media_id').unsigned().references('id').inTable('media');
|
table.integer('media_id').unsigned().references('id').inTable('media');
|
||||||
table.integer('model_id').unsigned().index();
|
table.integer('model_id').unsigned().index();
|
||||||
})
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.down = function(knex) {
|
exports.down = function (knex) {
|
||||||
return knex.schema.dropTableIfExists('media_links');
|
return knex.schema.dropTableIfExists('media_links');
|
||||||
};
|
};
|
||||||
|
|||||||
+16
-7
@@ -1,11 +1,20 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
exports.up = function(knex) {
|
return knex.schema.createTable('sales_receipts', (table) => {
|
||||||
return knex.schema.createTable('sales_receipts', table => {
|
|
||||||
table.increments();
|
table.increments();
|
||||||
table.decimal('amount', 13, 3);
|
table.decimal('amount', 13, 3);
|
||||||
table.string('currency_code', 3);
|
table.string('currency_code', 3);
|
||||||
table.integer('deposit_account_id').unsigned().index().references('id').inTable('accounts');
|
table
|
||||||
table.integer('customer_id').unsigned().index().references('id').inTable('contacts');
|
.integer('deposit_account_id')
|
||||||
|
.unsigned()
|
||||||
|
.index()
|
||||||
|
.references('id')
|
||||||
|
.inTable('accounts');
|
||||||
|
table
|
||||||
|
.integer('customer_id')
|
||||||
|
.unsigned()
|
||||||
|
.index()
|
||||||
|
.references('id')
|
||||||
|
.inTable('contacts');
|
||||||
table.date('receipt_date').index();
|
table.date('receipt_date').index();
|
||||||
table.string('receipt_number').index();
|
table.string('receipt_number').index();
|
||||||
table.string('reference_no').index();
|
table.string('reference_no').index();
|
||||||
@@ -14,9 +23,9 @@ exports.up = function(knex) {
|
|||||||
table.text('statement');
|
table.text('statement');
|
||||||
table.date('closed_at').index();
|
table.date('closed_at').index();
|
||||||
table.timestamps();
|
table.timestamps();
|
||||||
})
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.down = function(knex) {
|
exports.down = function (knex) {
|
||||||
return knex.schema.dropTableIfExists('sales_receipts');
|
return knex.schema.dropTableIfExists('sales_receipts');
|
||||||
};
|
};
|
||||||
|
|||||||
+15
-9
@@ -1,11 +1,19 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
exports.up = function(knex) {
|
return knex.schema.createTable('bills_payments', (table) => {
|
||||||
return knex.schema.createTable('bills_payments', table => {
|
|
||||||
table.increments();
|
table.increments();
|
||||||
table.integer('vendor_id').unsigned().index().references('id').inTable('contacts');
|
table
|
||||||
|
.integer('vendor_id')
|
||||||
|
.unsigned()
|
||||||
|
.index()
|
||||||
|
.references('id')
|
||||||
|
.inTable('contacts');
|
||||||
table.decimal('amount', 13, 3).defaultTo(0);
|
table.decimal('amount', 13, 3).defaultTo(0);
|
||||||
table.string('currency_code');
|
table.string('currency_code');
|
||||||
table.integer('payment_account_id').unsigned().references('id').inTable('accounts');
|
table
|
||||||
|
.integer('payment_account_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('accounts');
|
||||||
table.string('payment_number').nullable().index();
|
table.string('payment_number').nullable().index();
|
||||||
table.date('payment_date').index();
|
table.date('payment_date').index();
|
||||||
table.string('payment_method');
|
table.string('payment_method');
|
||||||
@@ -13,9 +21,7 @@ exports.up = function(knex) {
|
|||||||
table.integer('user_id').unsigned().index();
|
table.integer('user_id').unsigned().index();
|
||||||
table.text('statement');
|
table.text('statement');
|
||||||
table.timestamps();
|
table.timestamps();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.down = function(knex) {
|
exports.down = function (knex) {};
|
||||||
|
|
||||||
};
|
|
||||||
|
|||||||
+9
-10
@@ -1,11 +1,10 @@
|
|||||||
exports.up = function (knex) {
|
exports.up = function (knex) {
|
||||||
return knex.schema.createTable('inventory_transaction_meta', (table) => {
|
return knex.schema.createTable('inventory_transaction_meta', (table) => {
|
||||||
table.increments('id');
|
table.increments('id');
|
||||||
table.string('transaction_number');
|
table.string('transaction_number');
|
||||||
table.text('description');
|
table.text('description');
|
||||||
table.integer('inventory_transaction_id').unsigned();
|
table.integer('inventory_transaction_id').unsigned();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.down = function (knex) {};
|
exports.down = function (knex) {};
|
||||||
|
|
||||||
|
|||||||
+9
-6
@@ -1,19 +1,22 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
exports.up = function(knex) {
|
return knex.schema.createTable('inventory_adjustments', (table) => {
|
||||||
return knex.schema.createTable('inventory_adjustments', table => {
|
|
||||||
table.increments();
|
table.increments();
|
||||||
table.date('date').index();
|
table.date('date').index();
|
||||||
table.string('type').index();
|
table.string('type').index();
|
||||||
table.integer('adjustment_account_id').unsigned().references('id').inTable('accounts');
|
table
|
||||||
|
.integer('adjustment_account_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('accounts');
|
||||||
table.string('reason');
|
table.string('reason');
|
||||||
table.string('reference_no').index();
|
table.string('reference_no').index();
|
||||||
table.string('description');
|
table.string('description');
|
||||||
table.integer('user_id').unsigned();
|
table.integer('user_id').unsigned();
|
||||||
table.date('published_at');
|
table.date('published_at');
|
||||||
table.timestamps();
|
table.timestamps();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.down = function(knex) {
|
exports.down = function (knex) {
|
||||||
return knex.schema.dropTableIfExists('inventory_adjustments');
|
return knex.schema.dropTableIfExists('inventory_adjustments');
|
||||||
};
|
};
|
||||||
|
|||||||
+4
-4
@@ -1,16 +1,16 @@
|
|||||||
exports.up = (knex) => {
|
exports.up = (knex) => {
|
||||||
return knex.schema
|
return knex.schema
|
||||||
.raw(
|
.raw(
|
||||||
'ALTER TABLE CONTACTS CHANGE SHIPPING_ADDRESS_1 SHIPPING_ADDRESS1 VARCHAR(255)'
|
'ALTER TABLE CONTACTS CHANGE SHIPPING_ADDRESS_1 SHIPPING_ADDRESS1 VARCHAR(255)',
|
||||||
)
|
)
|
||||||
.raw(
|
.raw(
|
||||||
'ALTER TABLE CONTACTS CHANGE SHIPPING_ADDRESS_2 SHIPPING_ADDRESS2 VARCHAR(255)'
|
'ALTER TABLE CONTACTS CHANGE SHIPPING_ADDRESS_2 SHIPPING_ADDRESS2 VARCHAR(255)',
|
||||||
)
|
)
|
||||||
.raw(
|
.raw(
|
||||||
'ALTER TABLE CONTACTS CHANGE BILLING_ADDRESS_1 BILLING_ADDRESS1 VARCHAR(255)'
|
'ALTER TABLE CONTACTS CHANGE BILLING_ADDRESS_1 BILLING_ADDRESS1 VARCHAR(255)',
|
||||||
)
|
)
|
||||||
.raw(
|
.raw(
|
||||||
'ALTER TABLE CONTACTS CHANGE BILLING_ADDRESS_2 BILLING_ADDRESS2 VARCHAR(255)'
|
'ALTER TABLE CONTACTS CHANGE BILLING_ADDRESS_2 BILLING_ADDRESS2 VARCHAR(255)',
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -11,4 +11,4 @@ exports.up = function (knex) {
|
|||||||
|
|
||||||
exports.down = function (knex) {
|
exports.down = function (knex) {
|
||||||
return knex.schema.dropTableIfExists('storage');
|
return knex.schema.dropTableIfExists('storage');
|
||||||
};
|
};
|
||||||
|
|||||||
+1
-1
@@ -19,7 +19,7 @@ exports.up = function (knex) {
|
|||||||
table.boolean('categorized').defaultTo(false);
|
table.boolean('categorized').defaultTo(false);
|
||||||
table.string('plaid_transaction_id');
|
table.string('plaid_transaction_id');
|
||||||
table.timestamps();
|
table.timestamps();
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+17
-13
@@ -1,18 +1,22 @@
|
|||||||
// This migration changes the precision of the tax_amount_withheld column in the bills and sales_invoices tables from 8, 2 to 13, 2.
|
// This migration changes the precision of the tax_amount_withheld column in the bills and sales_invoices tables from 8, 2 to 13, 2.
|
||||||
// This migration is necessary to allow tax_amount_withheld filed to store values bigger than 999,999.99.
|
// This migration is necessary to allow tax_amount_withheld filed to store values bigger than 999,999.99.
|
||||||
|
|
||||||
exports.up = function(knex) {
|
exports.up = function (knex) {
|
||||||
return knex.schema.alterTable('bills', function (table) {
|
return knex.schema
|
||||||
table.decimal('tax_amount_withheld', 13, 2).alter();
|
.alterTable('bills', function (table) {
|
||||||
}).alterTable('sales_invoices', function (table) {
|
table.decimal('tax_amount_withheld', 13, 2).alter();
|
||||||
table.decimal('tax_amount_withheld', 13, 2).alter();
|
})
|
||||||
});
|
.alterTable('sales_invoices', function (table) {
|
||||||
|
table.decimal('tax_amount_withheld', 13, 2).alter();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.down = function(knex) {
|
exports.down = function (knex) {
|
||||||
return knex.schema.alterTable('bills', function (table) {
|
return knex.schema
|
||||||
table.decimal('tax_amount_withheld', 8, 2).alter();
|
.alterTable('bills', function (table) {
|
||||||
}).alterTable('sales_invoices', function (table) {
|
table.decimal('tax_amount_withheld', 8, 2).alter();
|
||||||
table.decimal('tax_amount_withheld', 8, 2).alter();
|
})
|
||||||
});
|
.alterTable('sales_invoices', function (table) {
|
||||||
};
|
table.decimal('tax_amount_withheld', 8, 2).alter();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ exports.up = function (knex) {
|
|||||||
return knex.schema.createTable('payment_integrations', (table) => {
|
return knex.schema.createTable('payment_integrations', (table) => {
|
||||||
table.increments('id');
|
table.increments('id');
|
||||||
table.string('service');
|
table.string('service');
|
||||||
table.string('name');
|
table.string('name');
|
||||||
table.string('slug');
|
table.string('slug');
|
||||||
table.boolean('payment_enabled').defaultTo(false);
|
table.boolean('payment_enabled').defaultTo(false);
|
||||||
table.boolean('payout_enabled').defaultTo(false);
|
table.boolean('payout_enabled').defaultTo(false);
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ exports.up = function (knex) {
|
|||||||
return knex.schema.alterTable('sales_invoices', (table) => {
|
return knex.schema.alterTable('sales_invoices', (table) => {
|
||||||
table.decimal('discount', 10, 2).nullable().after('credited_amount');
|
table.decimal('discount', 10, 2).nullable().after('credited_amount');
|
||||||
table.string('discount_type').nullable().after('discount');
|
table.string('discount_type').nullable().after('discount');
|
||||||
table.decimal('adjustment', 10, 2).nullable().after('discount_type');
|
table.decimal('adjustment', 10, 2).nullable().after('discount_type');
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -2,20 +2,20 @@
|
|||||||
* @param { import("knex").Knex } knex
|
* @param { import("knex").Knex } knex
|
||||||
* @returns { Promise<void> }
|
* @returns { Promise<void> }
|
||||||
*/
|
*/
|
||||||
exports.up = function(knex) {
|
exports.up = function (knex) {
|
||||||
return knex.schema.alterTable('sales_estimates', (table) => {
|
return knex.schema.alterTable('sales_estimates', (table) => {
|
||||||
table.decimal('discount', 10, 2).nullable().after('amount');
|
table.decimal('discount', 10, 2).nullable().after('amount');
|
||||||
table.string('discount_type').nullable().after('discount');
|
table.string('discount_type').nullable().after('discount');
|
||||||
|
|
||||||
table.decimal('adjustment', 10, 2).nullable().after('discount_type');
|
table.decimal('adjustment', 10, 2).nullable().after('discount_type');
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param { import("knex").Knex } knex
|
* @param { import("knex").Knex } knex
|
||||||
* @returns { Promise<void> }
|
* @returns { Promise<void> }
|
||||||
*/
|
*/
|
||||||
exports.down = function(knex) {
|
exports.down = function (knex) {
|
||||||
return knex.schema.alterTable('sales_estimates', (table) => {
|
return knex.schema.alterTable('sales_estimates', (table) => {
|
||||||
table.dropColumn('discount');
|
table.dropColumn('discount');
|
||||||
table.dropColumn('discount_type');
|
table.dropColumn('discount_type');
|
||||||
|
|||||||
+2
-2
@@ -2,7 +2,7 @@
|
|||||||
* @param { import("knex").Knex } knex
|
* @param { import("knex").Knex } knex
|
||||||
* @returns { Promise<void> }
|
* @returns { Promise<void> }
|
||||||
*/
|
*/
|
||||||
exports.up = function(knex) {
|
exports.up = function (knex) {
|
||||||
return knex.schema.alterTable('sales_receipts', (table) => {
|
return knex.schema.alterTable('sales_receipts', (table) => {
|
||||||
table.decimal('discount', 10, 2).nullable().after('amount');
|
table.decimal('discount', 10, 2).nullable().after('amount');
|
||||||
table.string('discount_type').nullable().after('discount');
|
table.string('discount_type').nullable().after('discount');
|
||||||
@@ -15,7 +15,7 @@ exports.up = function(knex) {
|
|||||||
* @param { import("knex").Knex } knex
|
* @param { import("knex").Knex } knex
|
||||||
* @returns { Promise<void> }
|
* @returns { Promise<void> }
|
||||||
*/
|
*/
|
||||||
exports.down = function(knex) {
|
exports.down = function (knex) {
|
||||||
return knex.schema.alterTable('sales_receipts', (table) => {
|
return knex.schema.alterTable('sales_receipts', (table) => {
|
||||||
table.dropColumn('discount');
|
table.dropColumn('discount');
|
||||||
table.dropColumn('discount_type');
|
table.dropColumn('discount_type');
|
||||||
|
|||||||
+2
-2
@@ -2,7 +2,7 @@
|
|||||||
* @param { import("knex").Knex } knex
|
* @param { import("knex").Knex } knex
|
||||||
* @returns { Promise<void> }
|
* @returns { Promise<void> }
|
||||||
*/
|
*/
|
||||||
exports.up = function(knex) {
|
exports.up = function (knex) {
|
||||||
return knex.schema.alterTable('bills', (table) => {
|
return knex.schema.alterTable('bills', (table) => {
|
||||||
// Discount.
|
// Discount.
|
||||||
table.decimal('discount', 10, 2).nullable().after('amount');
|
table.decimal('discount', 10, 2).nullable().after('amount');
|
||||||
@@ -17,7 +17,7 @@ exports.up = function(knex) {
|
|||||||
* @param { import("knex").Knex } knex
|
* @param { import("knex").Knex } knex
|
||||||
* @returns { Promise<void> }
|
* @returns { Promise<void> }
|
||||||
*/
|
*/
|
||||||
exports.down = function(knex) {
|
exports.down = function (knex) {
|
||||||
return knex.schema.alterTable('bills', (table) => {
|
return knex.schema.alterTable('bills', (table) => {
|
||||||
table.dropColumn('discount');
|
table.dropColumn('discount');
|
||||||
table.dropColumn('discount_type');
|
table.dropColumn('discount_type');
|
||||||
|
|||||||
+2
-2
@@ -2,7 +2,7 @@
|
|||||||
* @param { import("knex").Knex } knex
|
* @param { import("knex").Knex } knex
|
||||||
* @returns { Promise<void> }
|
* @returns { Promise<void> }
|
||||||
*/
|
*/
|
||||||
exports.up = function(knex) {
|
exports.up = function (knex) {
|
||||||
return knex.schema.alterTable('credit_notes', (table) => {
|
return knex.schema.alterTable('credit_notes', (table) => {
|
||||||
table.decimal('discount', 10, 2).nullable().after('exchange_rate');
|
table.decimal('discount', 10, 2).nullable().after('exchange_rate');
|
||||||
table.string('discount_type').nullable().after('discount');
|
table.string('discount_type').nullable().after('discount');
|
||||||
@@ -14,7 +14,7 @@ exports.up = function(knex) {
|
|||||||
* @param { import("knex").Knex } knex
|
* @param { import("knex").Knex } knex
|
||||||
* @returns { Promise<void> }
|
* @returns { Promise<void> }
|
||||||
*/
|
*/
|
||||||
exports.down = function(knex) {
|
exports.down = function (knex) {
|
||||||
return knex.schema.alterTable('credit_notes', (table) => {
|
return knex.schema.alterTable('credit_notes', (table) => {
|
||||||
table.dropColumn('discount');
|
table.dropColumn('discount');
|
||||||
table.dropColumn('discount_type');
|
table.dropColumn('discount_type');
|
||||||
|
|||||||
+2
-2
@@ -2,7 +2,7 @@
|
|||||||
* @param { import("knex").Knex } knex
|
* @param { import("knex").Knex } knex
|
||||||
* @returns { Promise<void> }
|
* @returns { Promise<void> }
|
||||||
*/
|
*/
|
||||||
exports.up = function(knex) {
|
exports.up = function (knex) {
|
||||||
return knex.schema.alterTable('vendor_credits', (table) => {
|
return knex.schema.alterTable('vendor_credits', (table) => {
|
||||||
table.decimal('discount', 10, 2).nullable().after('amount');
|
table.decimal('discount', 10, 2).nullable().after('amount');
|
||||||
table.string('discount_type').nullable().after('discount');
|
table.string('discount_type').nullable().after('discount');
|
||||||
@@ -14,7 +14,7 @@ exports.up = function(knex) {
|
|||||||
* @param { import("knex").Knex } knex
|
* @param { import("knex").Knex } knex
|
||||||
* @returns { Promise<void> }
|
* @returns { Promise<void> }
|
||||||
*/
|
*/
|
||||||
exports.down = function(knex) {
|
exports.down = function (knex) {
|
||||||
return knex.schema.alterTable('vendor_credits', (table) => {
|
return knex.schema.alterTable('vendor_credits', (table) => {
|
||||||
table.dropColumn('discount');
|
table.dropColumn('discount');
|
||||||
table.dropColumn('discount_type');
|
table.dropColumn('discount_type');
|
||||||
|
|||||||
+4
-5
@@ -1,12 +1,11 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
exports.up = function(knex) {
|
return knex.schema.alterTable('contacts', (table) => {
|
||||||
return knex.schema.alterTable('contacts', table => {
|
|
||||||
table.string('code').nullable().unique();
|
table.string('code').nullable().unique();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.down = function(knex) {
|
exports.down = function (knex) {
|
||||||
return knex.schema.alterTable('contacts', table => {
|
return knex.schema.alterTable('contacts', (table) => {
|
||||||
table.dropColumn('code');
|
table.dropColumn('code');
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
+3
-3
@@ -2,9 +2,9 @@ import { TenantSeeder } from '@/libs/migration-seed/TenantSeeder';
|
|||||||
|
|
||||||
export default class SeedSettings extends TenantSeeder {
|
export default class SeedSettings extends TenantSeeder {
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param knex
|
* @param knex
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
async up(knex) {
|
async up(knex) {
|
||||||
const costAccount = await knex('accounts')
|
const costAccount = await knex('accounts')
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
// .gitkeep
|
// .gitkeep
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ export class AccountTypesUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve account type by the given account type key.
|
* Retrieve account type by the given account type key.
|
||||||
* @param {string} key
|
* @param {string} key
|
||||||
* @param {string} accessor
|
* @param {string} accessor
|
||||||
*/
|
*/
|
||||||
static getType(key: string, accessor?: string) {
|
static getType(key: string, accessor?: string) {
|
||||||
const type = ACCOUNT_TYPES.find((type) => type.key === key);
|
const type = ACCOUNT_TYPES.find((type) => type.key === key);
|
||||||
@@ -34,7 +34,7 @@ export class AccountTypesUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve accounts types by the parent account type.
|
* Retrieve accounts types by the parent account type.
|
||||||
* @param {string} parentType
|
* @param {string} parentType
|
||||||
*/
|
*/
|
||||||
static getTypesByParentType(parentType: string) {
|
static getTypesByParentType(parentType: string) {
|
||||||
return ACCOUNT_TYPES.filter((type) => type.parentType === parentType);
|
return ACCOUNT_TYPES.filter((type) => type.parentType === parentType);
|
||||||
@@ -42,16 +42,16 @@ export class AccountTypesUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve accounts types by the given account normal.
|
* Retrieve accounts types by the given account normal.
|
||||||
* @param {string} normal
|
* @param {string} normal
|
||||||
*/
|
*/
|
||||||
static getTypesByNormal(normal: string) {
|
static getTypesByNormal(normal: string) {
|
||||||
return ACCOUNT_TYPES.filter((type) => type.normal === normal);
|
return ACCOUNT_TYPES.filter((type) => type.normal === normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detarmines whether the root type equals the account type.
|
* Detarmines whether the root type equals the account type.
|
||||||
* @param {string} key
|
* @param {string} key
|
||||||
* @param {string} rootType
|
* @param {string} rootType
|
||||||
*/
|
*/
|
||||||
static isRootTypeEqualsKey(key: string, rootType: string): boolean {
|
static isRootTypeEqualsKey(key: string, rootType: string): boolean {
|
||||||
return ACCOUNT_TYPES.some((type) => {
|
return ACCOUNT_TYPES.some((type) => {
|
||||||
@@ -79,7 +79,7 @@ export class AccountTypesUtils {
|
|||||||
/**
|
/**
|
||||||
* Detarmines whether account type has balance sheet.
|
* Detarmines whether account type has balance sheet.
|
||||||
* @param {string} key - Account type key.
|
* @param {string} key - Account type key.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static isTypeBalanceSheet(key: string): boolean {
|
static isTypeBalanceSheet(key: string): boolean {
|
||||||
return ACCOUNT_TYPES.some((type) => {
|
return ACCOUNT_TYPES.some((type) => {
|
||||||
@@ -98,4 +98,4 @@ export class AccountTypesUtils {
|
|||||||
return isType && type.incomeSheet;
|
return isType && type.incomeSheet;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ import { PageProperties } from './_types';
|
|||||||
export class ConverterUtils {
|
export class ConverterUtils {
|
||||||
public static injectPageProperties(
|
public static injectPageProperties(
|
||||||
data: FormData,
|
data: FormData,
|
||||||
pageProperties: PageProperties
|
pageProperties: PageProperties,
|
||||||
): void {
|
): void {
|
||||||
if (pageProperties.size) {
|
if (pageProperties.size) {
|
||||||
GotenbergUtils.assert(
|
GotenbergUtils.assert(
|
||||||
pageProperties.size.width >= 1.0 && pageProperties.size.height >= 1.5,
|
pageProperties.size.width >= 1.0 && pageProperties.size.height >= 1.5,
|
||||||
'size is smaller than the minimum printing requirements (i.e. 1.0 x 1.5 in)'
|
'size is smaller than the minimum printing requirements (i.e. 1.0 x 1.5 in)',
|
||||||
);
|
);
|
||||||
|
|
||||||
data.append('paperWidth', pageProperties.size.width);
|
data.append('paperWidth', pageProperties.size.width);
|
||||||
@@ -22,7 +22,7 @@ export class ConverterUtils {
|
|||||||
pageProperties.margins.bottom >= 0 &&
|
pageProperties.margins.bottom >= 0 &&
|
||||||
pageProperties.margins.left >= 0 &&
|
pageProperties.margins.left >= 0 &&
|
||||||
pageProperties.margins.left >= 0,
|
pageProperties.margins.left >= 0,
|
||||||
'negative margins are not allowed'
|
'negative margins are not allowed',
|
||||||
);
|
);
|
||||||
data.append('marginTop', pageProperties.margins.top);
|
data.append('marginTop', pageProperties.margins.top);
|
||||||
data.append('marginBottom', pageProperties.margins.bottom);
|
data.append('marginBottom', pageProperties.margins.bottom);
|
||||||
@@ -32,7 +32,7 @@ export class ConverterUtils {
|
|||||||
if (pageProperties.preferCssPageSize) {
|
if (pageProperties.preferCssPageSize) {
|
||||||
data.append(
|
data.append(
|
||||||
'preferCssPageSize',
|
'preferCssPageSize',
|
||||||
String(pageProperties.preferCssPageSize)
|
String(pageProperties.preferCssPageSize),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (pageProperties.printBackground) {
|
if (pageProperties.printBackground) {
|
||||||
@@ -44,7 +44,7 @@ export class ConverterUtils {
|
|||||||
if (pageProperties.scale) {
|
if (pageProperties.scale) {
|
||||||
GotenbergUtils.assert(
|
GotenbergUtils.assert(
|
||||||
pageProperties.scale >= 0.1 && pageProperties.scale <= 2.0,
|
pageProperties.scale >= 0.1 && pageProperties.scale <= 2.0,
|
||||||
'scale is outside of [0.1 - 2] range'
|
'scale is outside of [0.1 - 2] range',
|
||||||
);
|
);
|
||||||
data.append('scale', pageProperties.scale);
|
data.append('scale', pageProperties.scale);
|
||||||
}
|
}
|
||||||
@@ -55,11 +55,11 @@ export class ConverterUtils {
|
|||||||
pageProperties.nativePageRanges.to > 0 &&
|
pageProperties.nativePageRanges.to > 0 &&
|
||||||
pageProperties.nativePageRanges.to >=
|
pageProperties.nativePageRanges.to >=
|
||||||
pageProperties.nativePageRanges.from,
|
pageProperties.nativePageRanges.from,
|
||||||
'page ranges syntax error'
|
'page ranges syntax error',
|
||||||
);
|
);
|
||||||
data.append(
|
data.append(
|
||||||
'nativePageRanges',
|
'nativePageRanges',
|
||||||
`${pageProperties.nativePageRanges.from}-${pageProperties.nativePageRanges.to}`
|
`${pageProperties.nativePageRanges.from}-${pageProperties.nativePageRanges.to}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import * as FormData from 'form-data';
|
import * as FormData from 'form-data';
|
||||||
import { IConverter, PageProperties, PdfFormat, ChromiumRoute } from './_types';
|
import { IConverter, PageProperties, PdfFormat, ChromiumRoute } from './_types';
|
||||||
import { ConverterUtils } from './ConvertUtils';
|
import { ConverterUtils } from './ConvertUtils';
|
||||||
import { Converter } from './Converter';
|
import { Converter } from './Converter';
|
||||||
|
|||||||
@@ -14,337 +14,337 @@
|
|||||||
* @param circular A boolean to allow circular dependencies
|
* @param circular A boolean to allow circular dependencies
|
||||||
*/
|
*/
|
||||||
function createDFS(edges, leavesOnly, result, circular) {
|
function createDFS(edges, leavesOnly, result, circular) {
|
||||||
var visited = {};
|
var visited = {};
|
||||||
return function (start) {
|
return function (start) {
|
||||||
if (visited[start]) {
|
if (visited[start]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var inCurrentPath = {};
|
var inCurrentPath = {};
|
||||||
var currentPath = [];
|
var currentPath = [];
|
||||||
var todo = []; // used as a stack
|
var todo = []; // used as a stack
|
||||||
todo.push({ node: start, processed: false });
|
todo.push({ node: start, processed: false });
|
||||||
while (todo.length > 0) {
|
while (todo.length > 0) {
|
||||||
var current = todo[todo.length - 1]; // peek at the todo stack
|
var current = todo[todo.length - 1]; // peek at the todo stack
|
||||||
var processed = current.processed;
|
var processed = current.processed;
|
||||||
var node = current.node;
|
var node = current.node;
|
||||||
if (!processed) {
|
if (!processed) {
|
||||||
// Haven't visited edges yet (visiting phase)
|
// Haven't visited edges yet (visiting phase)
|
||||||
if (visited[node]) {
|
if (visited[node]) {
|
||||||
todo.pop();
|
|
||||||
continue;
|
|
||||||
} else if (inCurrentPath[node]) {
|
|
||||||
// It's not a DAG
|
|
||||||
if (circular) {
|
|
||||||
todo.pop();
|
|
||||||
// If we're tolerating cycles, don't revisit the node
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
currentPath.push(node);
|
|
||||||
throw new DepGraphCycleError(currentPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
inCurrentPath[node] = true;
|
|
||||||
currentPath.push(node);
|
|
||||||
var nodeEdges = edges[node];
|
|
||||||
// (push edges onto the todo stack in reverse order to be order-compatible with the old DFS implementation)
|
|
||||||
for (var i = nodeEdges.length - 1; i >= 0; i--) {
|
|
||||||
todo.push({ node: nodeEdges[i], processed: false });
|
|
||||||
}
|
|
||||||
current.processed = true;
|
|
||||||
} else {
|
|
||||||
// Have visited edges (stack unrolling phase)
|
|
||||||
todo.pop();
|
todo.pop();
|
||||||
currentPath.pop();
|
continue;
|
||||||
inCurrentPath[node] = false;
|
} else if (inCurrentPath[node]) {
|
||||||
visited[node] = true;
|
// It's not a DAG
|
||||||
if (!leavesOnly || edges[node].length === 0) {
|
if (circular) {
|
||||||
result.push(node);
|
todo.pop();
|
||||||
|
// If we're tolerating cycles, don't revisit the node
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
currentPath.push(node);
|
||||||
|
throw new DepGraphCycleError(currentPath);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
inCurrentPath[node] = true;
|
||||||
}
|
currentPath.push(node);
|
||||||
|
var nodeEdges = edges[node];
|
||||||
/**
|
// (push edges onto the todo stack in reverse order to be order-compatible with the old DFS implementation)
|
||||||
* Simple Dependency Graph
|
for (var i = nodeEdges.length - 1; i >= 0; i--) {
|
||||||
*/
|
todo.push({ node: nodeEdges[i], processed: false });
|
||||||
var DepGraph = (DepGraph = function DepGraph(opts) {
|
|
||||||
this.nodes = {}; // Node -> Node/Data (treated like a Set)
|
|
||||||
this.outgoingEdges = {}; // Node -> [Dependency Node]
|
|
||||||
this.incomingEdges = {}; // Node -> [Dependant Node]
|
|
||||||
this.circular = opts && !!opts.circular; // Allows circular deps
|
|
||||||
});
|
|
||||||
|
|
||||||
DepGraph.fromArray = (
|
|
||||||
items,
|
|
||||||
options = { itemId: 'id', parentItemId: 'parent_id' }
|
|
||||||
) => {
|
|
||||||
const depGraph = new DepGraph();
|
|
||||||
|
|
||||||
items.forEach((item) => {
|
|
||||||
depGraph.addNode(item[options.itemId], item);
|
|
||||||
});
|
|
||||||
items.forEach((item) => {
|
|
||||||
if (item[options.parentItemId]) {
|
|
||||||
depGraph.addDependency(item[options.parentItemId], item[options.itemId]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return depGraph;
|
|
||||||
};
|
|
||||||
|
|
||||||
DepGraph.prototype = {
|
|
||||||
/**
|
|
||||||
* The number of nodes in the graph.
|
|
||||||
*/
|
|
||||||
size: function () {
|
|
||||||
return Object.keys(this.nodes).length;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Add a node to the dependency graph. If a node already exists, this method will do nothing.
|
|
||||||
*/
|
|
||||||
addNode: function (node, data) {
|
|
||||||
if (!this.hasNode(node)) {
|
|
||||||
// Checking the arguments length allows the user to add a node with undefined data
|
|
||||||
if (arguments.length === 2) {
|
|
||||||
this.nodes[node] = data;
|
|
||||||
} else {
|
|
||||||
this.nodes[node] = node;
|
|
||||||
}
|
}
|
||||||
this.outgoingEdges[node] = [];
|
current.processed = true;
|
||||||
this.incomingEdges[node] = [];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Remove a node from the dependency graph. If a node does not exist, this method will do nothing.
|
|
||||||
*/
|
|
||||||
removeNode: function (node) {
|
|
||||||
if (this.hasNode(node)) {
|
|
||||||
delete this.nodes[node];
|
|
||||||
delete this.outgoingEdges[node];
|
|
||||||
delete this.incomingEdges[node];
|
|
||||||
[this.incomingEdges, this.outgoingEdges].forEach(function (edgeList) {
|
|
||||||
Object.keys(edgeList).forEach(function (key) {
|
|
||||||
var idx = edgeList[key].indexOf(node);
|
|
||||||
if (idx >= 0) {
|
|
||||||
edgeList[key].splice(idx, 1);
|
|
||||||
}
|
|
||||||
}, this);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Check if a node exists in the graph
|
|
||||||
*/
|
|
||||||
hasNode: function (node) {
|
|
||||||
return this.nodes.hasOwnProperty(node);
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Get the data associated with a node name
|
|
||||||
*/
|
|
||||||
getNodeData: function (node) {
|
|
||||||
if (this.hasNode(node)) {
|
|
||||||
return this.nodes[node];
|
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Node does not exist: ' + node);
|
// Have visited edges (stack unrolling phase)
|
||||||
|
todo.pop();
|
||||||
|
currentPath.pop();
|
||||||
|
inCurrentPath[node] = false;
|
||||||
|
visited[node] = true;
|
||||||
|
if (!leavesOnly || edges[node].length === 0) {
|
||||||
|
result.push(node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
};
|
||||||
/**
|
}
|
||||||
* Set the associated data for a given node name. If the node does not exist, this method will throw an error
|
|
||||||
*/
|
/**
|
||||||
setNodeData: function (node, data) {
|
* Simple Dependency Graph
|
||||||
if (this.hasNode(node)) {
|
*/
|
||||||
|
var DepGraph = (DepGraph = function DepGraph(opts) {
|
||||||
|
this.nodes = {}; // Node -> Node/Data (treated like a Set)
|
||||||
|
this.outgoingEdges = {}; // Node -> [Dependency Node]
|
||||||
|
this.incomingEdges = {}; // Node -> [Dependant Node]
|
||||||
|
this.circular = opts && !!opts.circular; // Allows circular deps
|
||||||
|
});
|
||||||
|
|
||||||
|
DepGraph.fromArray = (
|
||||||
|
items,
|
||||||
|
options = { itemId: 'id', parentItemId: 'parent_id' },
|
||||||
|
) => {
|
||||||
|
const depGraph = new DepGraph();
|
||||||
|
|
||||||
|
items.forEach((item) => {
|
||||||
|
depGraph.addNode(item[options.itemId], item);
|
||||||
|
});
|
||||||
|
items.forEach((item) => {
|
||||||
|
if (item[options.parentItemId]) {
|
||||||
|
depGraph.addDependency(item[options.parentItemId], item[options.itemId]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return depGraph;
|
||||||
|
};
|
||||||
|
|
||||||
|
DepGraph.prototype = {
|
||||||
|
/**
|
||||||
|
* The number of nodes in the graph.
|
||||||
|
*/
|
||||||
|
size: function () {
|
||||||
|
return Object.keys(this.nodes).length;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Add a node to the dependency graph. If a node already exists, this method will do nothing.
|
||||||
|
*/
|
||||||
|
addNode: function (node, data) {
|
||||||
|
if (!this.hasNode(node)) {
|
||||||
|
// Checking the arguments length allows the user to add a node with undefined data
|
||||||
|
if (arguments.length === 2) {
|
||||||
this.nodes[node] = data;
|
this.nodes[node] = data;
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Node does not exist: ' + node);
|
this.nodes[node] = node;
|
||||||
}
|
}
|
||||||
},
|
this.outgoingEdges[node] = [];
|
||||||
/**
|
this.incomingEdges[node] = [];
|
||||||
* Add a dependency between two nodes. If either of the nodes does not exist,
|
}
|
||||||
* an Error will be thrown.
|
},
|
||||||
*/
|
/**
|
||||||
addDependency: function (from, to) {
|
* Remove a node from the dependency graph. If a node does not exist, this method will do nothing.
|
||||||
if (!this.hasNode(from)) {
|
*/
|
||||||
throw new Error('Node does not exist: ' + from);
|
removeNode: function (node) {
|
||||||
}
|
if (this.hasNode(node)) {
|
||||||
if (!this.hasNode(to)) {
|
delete this.nodes[node];
|
||||||
throw new Error('Node does not exist: ' + to);
|
delete this.outgoingEdges[node];
|
||||||
}
|
delete this.incomingEdges[node];
|
||||||
if (this.outgoingEdges[from].indexOf(to) === -1) {
|
[this.incomingEdges, this.outgoingEdges].forEach(function (edgeList) {
|
||||||
this.outgoingEdges[from].push(to);
|
Object.keys(edgeList).forEach(function (key) {
|
||||||
}
|
var idx = edgeList[key].indexOf(node);
|
||||||
if (this.incomingEdges[to].indexOf(from) === -1) {
|
if (idx >= 0) {
|
||||||
this.incomingEdges[to].push(from);
|
edgeList[key].splice(idx, 1);
|
||||||
}
|
}
|
||||||
return true;
|
}, this);
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Remove a dependency between two nodes.
|
|
||||||
*/
|
|
||||||
removeDependency: function (from, to) {
|
|
||||||
var idx;
|
|
||||||
if (this.hasNode(from)) {
|
|
||||||
idx = this.outgoingEdges[from].indexOf(to);
|
|
||||||
if (idx >= 0) {
|
|
||||||
this.outgoingEdges[from].splice(idx, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.hasNode(to)) {
|
|
||||||
idx = this.incomingEdges[to].indexOf(from);
|
|
||||||
if (idx >= 0) {
|
|
||||||
this.incomingEdges[to].splice(idx, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Return a clone of the dependency graph. If any custom data is attached
|
|
||||||
* to the nodes, it will only be shallow copied.
|
|
||||||
*/
|
|
||||||
clone: function () {
|
|
||||||
var source = this;
|
|
||||||
var result = new DepGraph();
|
|
||||||
var keys = Object.keys(source.nodes);
|
|
||||||
keys.forEach(function (n) {
|
|
||||||
result.nodes[n] = source.nodes[n];
|
|
||||||
result.outgoingEdges[n] = source.outgoingEdges[n].slice(0);
|
|
||||||
result.incomingEdges[n] = source.incomingEdges[n].slice(0);
|
|
||||||
});
|
});
|
||||||
return result;
|
}
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Get an array containing the nodes that the specified node depends on (transitively).
|
* Check if a node exists in the graph
|
||||||
*
|
*/
|
||||||
* Throws an Error if the graph has a cycle, or the specified node does not exist.
|
hasNode: function (node) {
|
||||||
*
|
return this.nodes.hasOwnProperty(node);
|
||||||
* If `leavesOnly` is true, only nodes that do not depend on any other nodes will be returned
|
},
|
||||||
* in the array.
|
/**
|
||||||
*/
|
* Get the data associated with a node name
|
||||||
dependenciesOf: function (node, leavesOnly) {
|
*/
|
||||||
if (this.hasNode(node)) {
|
getNodeData: function (node) {
|
||||||
var result = [];
|
if (this.hasNode(node)) {
|
||||||
var DFS = createDFS(
|
return this.nodes[node];
|
||||||
this.outgoingEdges,
|
} else {
|
||||||
leavesOnly,
|
throw new Error('Node does not exist: ' + node);
|
||||||
result,
|
}
|
||||||
this.circular
|
},
|
||||||
);
|
|
||||||
DFS(node);
|
/**
|
||||||
var idx = result.indexOf(node);
|
* Set the associated data for a given node name. If the node does not exist, this method will throw an error
|
||||||
if (idx >= 0) {
|
*/
|
||||||
result.splice(idx, 1);
|
setNodeData: function (node, data) {
|
||||||
}
|
if (this.hasNode(node)) {
|
||||||
return result;
|
this.nodes[node] = data;
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Node does not exist: ' + node);
|
throw new Error('Node does not exist: ' + node);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Add a dependency between two nodes. If either of the nodes does not exist,
|
||||||
|
* an Error will be thrown.
|
||||||
|
*/
|
||||||
|
addDependency: function (from, to) {
|
||||||
|
if (!this.hasNode(from)) {
|
||||||
|
throw new Error('Node does not exist: ' + from);
|
||||||
|
}
|
||||||
|
if (!this.hasNode(to)) {
|
||||||
|
throw new Error('Node does not exist: ' + to);
|
||||||
|
}
|
||||||
|
if (this.outgoingEdges[from].indexOf(to) === -1) {
|
||||||
|
this.outgoingEdges[from].push(to);
|
||||||
|
}
|
||||||
|
if (this.incomingEdges[to].indexOf(from) === -1) {
|
||||||
|
this.incomingEdges[to].push(from);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Remove a dependency between two nodes.
|
||||||
|
*/
|
||||||
|
removeDependency: function (from, to) {
|
||||||
|
var idx;
|
||||||
|
if (this.hasNode(from)) {
|
||||||
|
idx = this.outgoingEdges[from].indexOf(to);
|
||||||
|
if (idx >= 0) {
|
||||||
|
this.outgoingEdges[from].splice(idx, 1);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
/**
|
|
||||||
* get an array containing the nodes that depend on the specified node (transitively).
|
if (this.hasNode(to)) {
|
||||||
*
|
idx = this.incomingEdges[to].indexOf(from);
|
||||||
* Throws an Error if the graph has a cycle, or the specified node does not exist.
|
if (idx >= 0) {
|
||||||
*
|
this.incomingEdges[to].splice(idx, 1);
|
||||||
* If `leavesOnly` is true, only nodes that do not have any dependants will be returned in the array.
|
|
||||||
*/
|
|
||||||
dependantsOf: function (node, leavesOnly) {
|
|
||||||
if (this.hasNode(node)) {
|
|
||||||
var result = [];
|
|
||||||
var DFS = createDFS(
|
|
||||||
this.incomingEdges,
|
|
||||||
leavesOnly,
|
|
||||||
result,
|
|
||||||
this.circular
|
|
||||||
);
|
|
||||||
DFS(node);
|
|
||||||
var idx = result.indexOf(node);
|
|
||||||
if (idx >= 0) {
|
|
||||||
result.splice(idx, 1);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
throw new Error('Node does not exist: ' + node);
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
/**
|
},
|
||||||
* Construct the overall processing order for the dependency graph.
|
/**
|
||||||
*
|
* Return a clone of the dependency graph. If any custom data is attached
|
||||||
* Throws an Error if the graph has a cycle.
|
* to the nodes, it will only be shallow copied.
|
||||||
*
|
*/
|
||||||
* If `leavesOnly` is true, only nodes that do not depend on any other nodes will be returned.
|
clone: function () {
|
||||||
*/
|
var source = this;
|
||||||
overallOrder: function (leavesOnly) {
|
var result = new DepGraph();
|
||||||
var self = this;
|
var keys = Object.keys(source.nodes);
|
||||||
|
keys.forEach(function (n) {
|
||||||
|
result.nodes[n] = source.nodes[n];
|
||||||
|
result.outgoingEdges[n] = source.outgoingEdges[n].slice(0);
|
||||||
|
result.incomingEdges[n] = source.incomingEdges[n].slice(0);
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Get an array containing the nodes that the specified node depends on (transitively).
|
||||||
|
*
|
||||||
|
* Throws an Error if the graph has a cycle, or the specified node does not exist.
|
||||||
|
*
|
||||||
|
* If `leavesOnly` is true, only nodes that do not depend on any other nodes will be returned
|
||||||
|
* in the array.
|
||||||
|
*/
|
||||||
|
dependenciesOf: function (node, leavesOnly) {
|
||||||
|
if (this.hasNode(node)) {
|
||||||
var result = [];
|
var result = [];
|
||||||
var keys = Object.keys(this.nodes);
|
var DFS = createDFS(
|
||||||
if (keys.length === 0) {
|
this.outgoingEdges,
|
||||||
return result; // Empty graph
|
leavesOnly,
|
||||||
} else {
|
result,
|
||||||
if (!this.circular) {
|
this.circular,
|
||||||
// Look for cycles - we run the DFS starting at all the nodes in case there
|
);
|
||||||
// are several disconnected subgraphs inside this dependency graph.
|
DFS(node);
|
||||||
var CycleDFS = createDFS(this.outgoingEdges, false, [], this.circular);
|
var idx = result.indexOf(node);
|
||||||
keys.forEach(function (n) {
|
if (idx >= 0) {
|
||||||
CycleDFS(n);
|
result.splice(idx, 1);
|
||||||
});
|
}
|
||||||
}
|
return result;
|
||||||
|
} else {
|
||||||
var DFS = createDFS(
|
throw new Error('Node does not exist: ' + node);
|
||||||
this.outgoingEdges,
|
}
|
||||||
leavesOnly,
|
},
|
||||||
result,
|
/**
|
||||||
this.circular
|
* get an array containing the nodes that depend on the specified node (transitively).
|
||||||
);
|
*
|
||||||
// Find all potential starting points (nodes with nothing depending on them) an
|
* Throws an Error if the graph has a cycle, or the specified node does not exist.
|
||||||
// run a DFS starting at these points to get the order
|
*
|
||||||
|
* If `leavesOnly` is true, only nodes that do not have any dependants will be returned in the array.
|
||||||
|
*/
|
||||||
|
dependantsOf: function (node, leavesOnly) {
|
||||||
|
if (this.hasNode(node)) {
|
||||||
|
var result = [];
|
||||||
|
var DFS = createDFS(
|
||||||
|
this.incomingEdges,
|
||||||
|
leavesOnly,
|
||||||
|
result,
|
||||||
|
this.circular,
|
||||||
|
);
|
||||||
|
DFS(node);
|
||||||
|
var idx = result.indexOf(node);
|
||||||
|
if (idx >= 0) {
|
||||||
|
result.splice(idx, 1);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
throw new Error('Node does not exist: ' + node);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Construct the overall processing order for the dependency graph.
|
||||||
|
*
|
||||||
|
* Throws an Error if the graph has a cycle.
|
||||||
|
*
|
||||||
|
* If `leavesOnly` is true, only nodes that do not depend on any other nodes will be returned.
|
||||||
|
*/
|
||||||
|
overallOrder: function (leavesOnly) {
|
||||||
|
var self = this;
|
||||||
|
var result = [];
|
||||||
|
var keys = Object.keys(this.nodes);
|
||||||
|
if (keys.length === 0) {
|
||||||
|
return result; // Empty graph
|
||||||
|
} else {
|
||||||
|
if (!this.circular) {
|
||||||
|
// Look for cycles - we run the DFS starting at all the nodes in case there
|
||||||
|
// are several disconnected subgraphs inside this dependency graph.
|
||||||
|
var CycleDFS = createDFS(this.outgoingEdges, false, [], this.circular);
|
||||||
|
keys.forEach(function (n) {
|
||||||
|
CycleDFS(n);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var DFS = createDFS(
|
||||||
|
this.outgoingEdges,
|
||||||
|
leavesOnly,
|
||||||
|
result,
|
||||||
|
this.circular,
|
||||||
|
);
|
||||||
|
// Find all potential starting points (nodes with nothing depending on them) an
|
||||||
|
// run a DFS starting at these points to get the order
|
||||||
|
keys
|
||||||
|
.filter(function (node) {
|
||||||
|
return self.incomingEdges[node].length === 0;
|
||||||
|
})
|
||||||
|
.forEach(function (n) {
|
||||||
|
DFS(n);
|
||||||
|
});
|
||||||
|
|
||||||
|
// If we're allowing cycles - we need to run the DFS against any remaining
|
||||||
|
// nodes that did not end up in the initial result (as they are part of a
|
||||||
|
// subgraph that does not have a clear starting point)
|
||||||
|
if (this.circular) {
|
||||||
keys
|
keys
|
||||||
.filter(function (node) {
|
.filter(function (node) {
|
||||||
return self.incomingEdges[node].length === 0;
|
return result.indexOf(node) === -1;
|
||||||
})
|
})
|
||||||
.forEach(function (n) {
|
.forEach(function (n) {
|
||||||
DFS(n);
|
DFS(n);
|
||||||
});
|
});
|
||||||
|
|
||||||
// If we're allowing cycles - we need to run the DFS against any remaining
|
|
||||||
// nodes that did not end up in the initial result (as they are part of a
|
|
||||||
// subgraph that does not have a clear starting point)
|
|
||||||
if (this.circular) {
|
|
||||||
keys
|
|
||||||
.filter(function (node) {
|
|
||||||
return result.indexOf(node) === -1;
|
|
||||||
})
|
|
||||||
.forEach(function (n) {
|
|
||||||
DFS(n);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
return result;
|
||||||
mapNodes(mapper) {},
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cycle error, including the path of the cycle.
|
|
||||||
*/
|
|
||||||
var DepGraphCycleError = (exports.DepGraphCycleError = function (cyclePath) {
|
|
||||||
var message = 'Dependency Cycle Found: ' + cyclePath.join(' -> ');
|
|
||||||
var instance = new Error(message);
|
|
||||||
instance.cyclePath = cyclePath;
|
|
||||||
Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
|
|
||||||
if (Error.captureStackTrace) {
|
|
||||||
Error.captureStackTrace(instance, DepGraphCycleError);
|
|
||||||
}
|
}
|
||||||
return instance;
|
},
|
||||||
});
|
|
||||||
DepGraphCycleError.prototype = Object.create(Error.prototype, {
|
mapNodes(mapper) {},
|
||||||
constructor: {
|
};
|
||||||
value: Error,
|
|
||||||
enumerable: false,
|
/**
|
||||||
writable: true,
|
* Cycle error, including the path of the cycle.
|
||||||
configurable: true,
|
*/
|
||||||
},
|
var DepGraphCycleError = (exports.DepGraphCycleError = function (cyclePath) {
|
||||||
});
|
var message = 'Dependency Cycle Found: ' + cyclePath.join(' -> ');
|
||||||
Object.setPrototypeOf(DepGraphCycleError, Error);
|
var instance = new Error(message);
|
||||||
|
instance.cyclePath = cyclePath;
|
||||||
export default DepGraph;
|
Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
|
||||||
|
if (Error.captureStackTrace) {
|
||||||
|
Error.captureStackTrace(instance, DepGraphCycleError);
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
});
|
||||||
|
DepGraphCycleError.prototype = Object.create(Error.prototype, {
|
||||||
|
constructor: {
|
||||||
|
value: Error,
|
||||||
|
enumerable: false,
|
||||||
|
writable: true,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
Object.setPrototypeOf(DepGraphCycleError, Error);
|
||||||
|
|
||||||
|
export default DepGraph;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
const OperationType = {
|
const OperationType = {
|
||||||
LOGIC: 'LOGIC',
|
LOGIC: 'LOGIC',
|
||||||
STRING: 'STRING',
|
STRING: 'STRING',
|
||||||
@@ -20,7 +19,7 @@ export class Lexer {
|
|||||||
'?': OperationType.LOGIC,
|
'?': OperationType.LOGIC,
|
||||||
':': OperationType.LOGIC,
|
':': OperationType.LOGIC,
|
||||||
|
|
||||||
'\'': OperationType.STRING,
|
"'": OperationType.STRING,
|
||||||
'"': OperationType.STRING,
|
'"': OperationType.STRING,
|
||||||
|
|
||||||
'!': OperationType.COMPARISON,
|
'!': OperationType.COMPARISON,
|
||||||
@@ -79,11 +78,13 @@ export class Lexer {
|
|||||||
// we must move the pos forward
|
// we must move the pos forward
|
||||||
// so here we should throw error, for example `1 & 2`
|
// so here we should throw error, for example `1 & 2`
|
||||||
if (pos === this.currentIndex && tok !== undefined) {
|
if (pos === this.currentIndex && tok !== undefined) {
|
||||||
const err = new Error(`unkonw token ${tok} from input string ${this.input}`);
|
const err = new Error(
|
||||||
|
`unkonw token ${tok} from input string ${this.input}`,
|
||||||
|
);
|
||||||
err.name = 'UnknowToken';
|
err.name = 'UnknowToken';
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
} while (tok !== undefined)
|
} while (tok !== undefined);
|
||||||
|
|
||||||
return this.tokenList;
|
return this.tokenList;
|
||||||
}
|
}
|
||||||
@@ -103,7 +104,9 @@ export class Lexer {
|
|||||||
* @param index
|
* @param index
|
||||||
*/
|
*/
|
||||||
receiveToken(index = 1) {
|
receiveToken(index = 1) {
|
||||||
const tok = this.input.slice(this.currentIndex, this.currentIndex + index).trim();
|
const tok = this.input
|
||||||
|
.slice(this.currentIndex, this.currentIndex + index)
|
||||||
|
.trim();
|
||||||
// skip empty string
|
// skip empty string
|
||||||
if (tok) {
|
if (tok) {
|
||||||
this.tokenList.push(tok);
|
this.tokenList.push(tok);
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ export class Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @return {Node | string} =-
|
* @return {Node | string} =-
|
||||||
*/
|
*/
|
||||||
parse() {
|
parse() {
|
||||||
let tok;
|
let tok;
|
||||||
@@ -67,7 +67,9 @@ export class Parser {
|
|||||||
root.right = this.parseStatement();
|
root.right = this.parseStatement();
|
||||||
} else {
|
} else {
|
||||||
if (typeof tok !== 'string') {
|
if (typeof tok !== 'string') {
|
||||||
throw new Error('operation must be string, but get ' + JSON.stringify(tok));
|
throw new Error(
|
||||||
|
'operation must be string, but get ' + JSON.stringify(tok),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
root = this.addNode(tok, this.parseStatement(), root);
|
root = this.addNode(tok, this.parseStatement(), root);
|
||||||
}
|
}
|
||||||
@@ -86,19 +88,21 @@ export class Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {string} operation
|
* @param {string} operation
|
||||||
* @param {Node|String|null} right
|
* @param {Node|String|null} right
|
||||||
* @param {Node} root
|
* @param {Node} root
|
||||||
*/
|
*/
|
||||||
addNode(operation, right, root) {
|
addNode(operation, right, root) {
|
||||||
let pre = root;
|
let pre = root;
|
||||||
|
|
||||||
if (this.compare(pre.operation, operation) < 0 && !pre.grouped) {
|
if (this.compare(pre.operation, operation) < 0 && !pre.grouped) {
|
||||||
|
while (
|
||||||
while (pre.right !== null &&
|
pre.right !== null &&
|
||||||
typeof pre.right !== 'string' &&
|
typeof pre.right !== 'string' &&
|
||||||
this.compare(pre.right.operation, operation) < 0 && !pre.right.grouped) {
|
this.compare(pre.right.operation, operation) < 0 &&
|
||||||
|
!pre.right.grouped
|
||||||
|
) {
|
||||||
pre = pre.right;
|
pre = pre.right;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,13 +117,13 @@ export class Parser {
|
|||||||
left: pre,
|
left: pre,
|
||||||
right,
|
right,
|
||||||
operation,
|
operation,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {String} a
|
* @param {String} a
|
||||||
* @param {String} b
|
* @param {String} b
|
||||||
*/
|
*/
|
||||||
compare(a, b) {
|
compare(a, b) {
|
||||||
if (!OPERATION.hasOwnProperty(a) || !OPERATION.hasOwnProperty(b)) {
|
if (!OPERATION.hasOwnProperty(a) || !OPERATION.hasOwnProperty(b)) {
|
||||||
@@ -149,12 +153,20 @@ export class Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (token === '!') {
|
if (token === '!') {
|
||||||
return { left: null, operation: token, right: this.parseStatement() }
|
return { left: null, operation: token, right: this.parseStatement() };
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3 > -12 or -12 + 10
|
// 3 > -12 or -12 + 10
|
||||||
if (token === '-' && (OPERATION[this.prevToken()] > 0 || this.prevToken() === undefined)) {
|
if (
|
||||||
return { left: '0', operation: token, right: this.parseStatement(), grouped: true };
|
token === '-' &&
|
||||||
|
(OPERATION[this.prevToken()] > 0 || this.prevToken() === undefined)
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
left: '0',
|
||||||
|
operation: token,
|
||||||
|
right: this.parseStatement(),
|
||||||
|
grouped: true,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return token;
|
return token;
|
||||||
|
|||||||
@@ -22,7 +22,9 @@ export class QueryParser {
|
|||||||
parseNode(node) {
|
parseNode(node) {
|
||||||
if (typeof node === 'string') {
|
if (typeof node === 'string') {
|
||||||
const nodeQuery = this.getQuery(node);
|
const nodeQuery = this.getQuery(node);
|
||||||
return (query) => { nodeQuery(query); };
|
return (query) => {
|
||||||
|
nodeQuery(query);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
if (OPERATION[node.operation] === undefined) {
|
if (OPERATION[node.operation] === undefined) {
|
||||||
throw new Error(`unknow expression ${node.operation}`);
|
throw new Error(`unknow expression ${node.operation}`);
|
||||||
@@ -34,16 +36,26 @@ export class QueryParser {
|
|||||||
case '&&':
|
case '&&':
|
||||||
case 'AND':
|
case 'AND':
|
||||||
default:
|
default:
|
||||||
return (nodeQuery) => nodeQuery.where((query) => {
|
return (nodeQuery) =>
|
||||||
query.where((q) => { leftQuery(q); });
|
nodeQuery.where((query) => {
|
||||||
query.andWhere((q) => { rightQuery(q); });
|
query.where((q) => {
|
||||||
});
|
leftQuery(q);
|
||||||
|
});
|
||||||
|
query.andWhere((q) => {
|
||||||
|
rightQuery(q);
|
||||||
|
});
|
||||||
|
});
|
||||||
case '||':
|
case '||':
|
||||||
case 'OR':
|
case 'OR':
|
||||||
return (nodeQuery) => nodeQuery.where((query) => {
|
return (nodeQuery) =>
|
||||||
query.where((q) => { leftQuery(q); });
|
nodeQuery.where((query) => {
|
||||||
query.orWhere((q) => { rightQuery(q); });
|
query.where((q) => {
|
||||||
});
|
leftQuery(q);
|
||||||
|
});
|
||||||
|
query.orWhere((q) => {
|
||||||
|
rightQuery(q);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,4 +73,4 @@ export class QueryParser {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
export class Seeder {
|
export class Seeder {
|
||||||
knex: any;
|
knex: any;
|
||||||
|
|
||||||
@@ -8,4 +7,3 @@ export class Seeder {
|
|||||||
up(knex) {}
|
up(knex) {}
|
||||||
down(knex) {}
|
down(knex) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export default function getMergedConfig(config, currentConfig) {
|
|||||||
mergedConfig.migrationSource = new FsMigrations(
|
mergedConfig.migrationSource = new FsMigrations(
|
||||||
mergedConfig.directory,
|
mergedConfig.directory,
|
||||||
mergedConfig.sortDirsSeparately,
|
mergedConfig.sortDirsSeparately,
|
||||||
mergedConfig.loadExtensions
|
mergedConfig.loadExtensions,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return mergedConfig;
|
return mergedConfig;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export function getLockTableName(tableName: string): string {
|
|||||||
*/
|
*/
|
||||||
export function getLockTableNameWithSchema(
|
export function getLockTableNameWithSchema(
|
||||||
tableName: string,
|
tableName: string,
|
||||||
schemaName = null
|
schemaName = null,
|
||||||
): string {
|
): string {
|
||||||
return schemaName
|
return schemaName
|
||||||
? `${schemaName} + ${getLockTableName(tableName)}`
|
? `${schemaName} + ${getLockTableName(tableName)}`
|
||||||
|
|||||||
@@ -50,13 +50,14 @@ export class PaginationQueryBuilder<
|
|||||||
return this.delete();
|
return this.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only check HasManyRelation and ManyToManyRelation relations, as BelongsToOneRelation are just
|
// Only check HasManyRelation and ManyToManyRelation relations, as BelongsToOneRelation are just
|
||||||
// foreign key references and shouldn't prevent deletion. Only dependent records should block deletion.
|
// foreign key references and shouldn't prevent deletion. Only dependent records should block deletion.
|
||||||
const dependentRelationNames = relationNames.filter((name) => {
|
const dependentRelationNames = relationNames.filter((name) => {
|
||||||
const relation = relationMappings[name];
|
const relation = relationMappings[name];
|
||||||
return relation && (
|
return (
|
||||||
relation.relation === Model.HasManyRelation ||
|
relation &&
|
||||||
relation.relation === Model.ManyToManyRelation
|
(relation.relation === Model.HasManyRelation ||
|
||||||
|
relation.relation === Model.ManyToManyRelation)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ import { Model } from 'objection';
|
|||||||
|
|
||||||
type Constructor<T = {}> = new (...args: any[]) => T;
|
type Constructor<T = {}> = new (...args: any[]) => T;
|
||||||
|
|
||||||
export const withDateSessionMixin = <T extends Constructor<Model>>(BaseModel: T) => {
|
export const withDateSessionMixin = <T extends Constructor<Model>>(
|
||||||
|
BaseModel: T,
|
||||||
|
) => {
|
||||||
return class DateSession extends BaseModel {
|
return class DateSession extends BaseModel {
|
||||||
constructor(...args: any[]) {
|
constructor(...args: any[]) {
|
||||||
super(...args);
|
super(...args);
|
||||||
@@ -12,7 +14,7 @@ export const withDateSessionMixin = <T extends Constructor<Model>>(BaseModel: T)
|
|||||||
get timestamps() {
|
get timestamps() {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
$beforeUpdate(opt, context) {
|
$beforeUpdate(opt, context) {
|
||||||
const maybePromise = super.$beforeUpdate(opt, context);
|
const maybePromise = super.$beforeUpdate(opt, context);
|
||||||
|
|
||||||
@@ -36,5 +38,5 @@ export const withDateSessionMixin = <T extends Constructor<Model>>(BaseModel: T)
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ import { AccountAction } from './Accounts.types';
|
|||||||
@ApiCommonHeaders()
|
@ApiCommonHeaders()
|
||||||
@UseGuards(AuthorizationGuard, PermissionGuard)
|
@UseGuards(AuthorizationGuard, PermissionGuard)
|
||||||
export class AccountsController {
|
export class AccountsController {
|
||||||
constructor(private readonly accountsApplication: AccountsApplication) { }
|
constructor(private readonly accountsApplication: AccountsApplication) {}
|
||||||
|
|
||||||
@Post('validate-bulk-delete')
|
@Post('validate-bulk-delete')
|
||||||
@HttpCode(200)
|
@HttpCode(200)
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export class AccountsApplication {
|
|||||||
private readonly getAccountsService: GetAccountsService,
|
private readonly getAccountsService: GetAccountsService,
|
||||||
private readonly bulkDeleteAccountsService: BulkDeleteAccountsService,
|
private readonly bulkDeleteAccountsService: BulkDeleteAccountsService,
|
||||||
private readonly validateBulkDeleteAccountsService: ValidateBulkDeleteAccountsService,
|
private readonly validateBulkDeleteAccountsService: ValidateBulkDeleteAccountsService,
|
||||||
) { }
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new account.
|
* Creates a new account.
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { Account } from './models/Account.model';
|
|||||||
@Global()
|
@Global()
|
||||||
export class AccountsExportable extends Exportable {
|
export class AccountsExportable extends Exportable {
|
||||||
/**
|
/**
|
||||||
* @param {AccountsApplication} accountsApplication
|
* @param {AccountsApplication} accountsApplication
|
||||||
*/
|
*/
|
||||||
constructor(private readonly accountsApplication: AccountsApplication) {
|
constructor(private readonly accountsApplication: AccountsApplication) {
|
||||||
super();
|
super();
|
||||||
|
|||||||
@@ -23,10 +23,7 @@ export class AccountsImportable extends Importable {
|
|||||||
createAccountDTO: CreateAccountDTO,
|
createAccountDTO: CreateAccountDTO,
|
||||||
trx?: Knex.Transaction,
|
trx?: Knex.Transaction,
|
||||||
) {
|
) {
|
||||||
return this.createAccountService.createAccount(
|
return this.createAccountService.createAccount(createAccountDTO, trx);
|
||||||
createAccountDTO,
|
|
||||||
trx,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { DeleteAccount } from './DeleteAccount.service';
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class BulkDeleteAccountsService {
|
export class BulkDeleteAccountsService {
|
||||||
constructor(private readonly deleteAccountService: DeleteAccount) { }
|
constructor(private readonly deleteAccountService: DeleteAccount) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes multiple accounts.
|
* Deletes multiple accounts.
|
||||||
@@ -38,4 +38,3 @@ export class BulkDeleteAccountsService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export class CommandAccountValidators {
|
|||||||
@Inject(Account.name)
|
@Inject(Account.name)
|
||||||
private readonly accountModel: TenantModelProxy<typeof Account>,
|
private readonly accountModel: TenantModelProxy<typeof Account>,
|
||||||
private readonly accountRepository: AccountRepository,
|
private readonly accountRepository: AccountRepository,
|
||||||
) { }
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Throws error if the account was prefined.
|
* Throws error if the account was prefined.
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export class DeleteAccount {
|
|||||||
private eventEmitter: EventEmitter2,
|
private eventEmitter: EventEmitter2,
|
||||||
private uow: UnitOfWork,
|
private uow: UnitOfWork,
|
||||||
private validator: CommandAccountValidators,
|
private validator: CommandAccountValidators,
|
||||||
) { }
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authorize account delete.
|
* Authorize account delete.
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { AccountTypesUtils } from './utils/AccountType.utils';
|
|||||||
export class GetAccountTypesService {
|
export class GetAccountTypesService {
|
||||||
/**
|
/**
|
||||||
* Retrieve all accounts types.
|
* Retrieve all accounts types.
|
||||||
* @param {number} tenantId -
|
* @param {number} tenantId -
|
||||||
* @return {IAccountType}
|
* @return {IAccountType}
|
||||||
*/
|
*/
|
||||||
public getAccountsTypes() {
|
public getAccountsTypes() {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export class GetAccountsService {
|
|||||||
|
|
||||||
@Inject(Account.name)
|
@Inject(Account.name)
|
||||||
private readonly accountModel: TenantModelProxy<typeof Account>,
|
private readonly accountModel: TenantModelProxy<typeof Account>,
|
||||||
) { }
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve accounts datatable list.
|
* Retrieve accounts datatable list.
|
||||||
|
|||||||
@@ -60,4 +60,3 @@ export class ValidateBulkDeleteAccountsService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,20 @@
|
|||||||
import { IsArray, IsBoolean, IsEnum, IsInt, IsOptional, IsString, Min } from 'class-validator';
|
import {
|
||||||
|
IsArray,
|
||||||
|
IsBoolean,
|
||||||
|
IsEnum,
|
||||||
|
IsInt,
|
||||||
|
IsOptional,
|
||||||
|
IsString,
|
||||||
|
Min,
|
||||||
|
} from 'class-validator';
|
||||||
import { ApiPropertyOptional } from '@nestjs/swagger';
|
import { ApiPropertyOptional } from '@nestjs/swagger';
|
||||||
import { Transform } from 'class-transformer';
|
import { Transform } from 'class-transformer';
|
||||||
import { parseBoolean } from '@/utils/parse-boolean';
|
import { parseBoolean } from '@/utils/parse-boolean';
|
||||||
import { IAccountsStructureType } from '../Accounts.types';
|
import { IAccountsStructureType } from '../Accounts.types';
|
||||||
import { IFilterRole, ISortOrder } from '@/modules/DynamicListing/DynamicFilter/DynamicFilter.types';
|
import {
|
||||||
|
IFilterRole,
|
||||||
|
ISortOrder,
|
||||||
|
} from '@/modules/DynamicListing/DynamicFilter/DynamicFilter.types';
|
||||||
import { ToNumber } from '@/common/decorators/Validators';
|
import { ToNumber } from '@/common/decorators/Validators';
|
||||||
|
|
||||||
export class GetAccountsQueryDto {
|
export class GetAccountsQueryDto {
|
||||||
@@ -114,4 +125,3 @@ export class GetAccountsQueryDto {
|
|||||||
@Min(1)
|
@Min(1)
|
||||||
pageSize?: number;
|
pageSize?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ACCOUNT_TYPES } from "../Accounts.constants";
|
import { ACCOUNT_TYPES } from '../Accounts.constants';
|
||||||
|
|
||||||
export const AccountMeta = {
|
export const AccountMeta = {
|
||||||
defaultFilterField: 'name',
|
defaultFilterField: 'name',
|
||||||
@@ -196,4 +196,4 @@ function RootTypeFieldFilterQuery(query, role) {
|
|||||||
*/
|
*/
|
||||||
function NormalTypeFieldFilterQuery(query, role) {
|
function NormalTypeFieldFilterQuery(query, role) {
|
||||||
query.modify('filterByAccountNormal', role.value);
|
query.modify('filterByAccountNormal', role.value);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-5
@@ -14,11 +14,9 @@ export class MutateBaseCurrencyAccountsSubscriber {
|
|||||||
* of the organization is mutated.
|
* of the organization is mutated.
|
||||||
*/
|
*/
|
||||||
@OnEvent(events.organization.baseCurrencyUpdated)
|
@OnEvent(events.organization.baseCurrencyUpdated)
|
||||||
async updateAccountsCurrencyOnBaseCurrencyMutated({
|
async updateAccountsCurrencyOnBaseCurrencyMutated({ organizationDTO }) {
|
||||||
organizationDTO,
|
|
||||||
}) {
|
|
||||||
await this.mutateBaseCurrencyAccounts.mutateAllAccountsCurrency(
|
await this.mutateBaseCurrencyAccounts.mutateAllAccountsCurrency(
|
||||||
organizationDTO.baseCurrency
|
organizationDTO.baseCurrency,
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ describe('AppController', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('root', () => {
|
describe('root', () => {
|
||||||
it('should return "Hello World!"', () => {
|
it('should return "Hello World!"', () => {});
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ import { ThrottlerStorageRedisService } from '@nest-lab/throttler-storage-redis'
|
|||||||
inject: [ConfigService],
|
inject: [ConfigService],
|
||||||
useFactory: (configService: ConfigService) => {
|
useFactory: (configService: ConfigService) => {
|
||||||
// Use in-memory storage with very high limits for test environment
|
// Use in-memory storage with very high limits for test environment
|
||||||
const isTest = process.env.NODE_ENV === 'test' || process.env.JEST_WORKER_ID !== undefined;
|
const isTest =
|
||||||
|
process.env.NODE_ENV === 'test' ||
|
||||||
|
process.env.JEST_WORKER_ID !== undefined;
|
||||||
|
|
||||||
if (isTest) {
|
if (isTest) {
|
||||||
return {
|
return {
|
||||||
@@ -64,6 +66,4 @@ import { ThrottlerStorageRedisService } from '@nest-lab/throttler-storage-redis'
|
|||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class AppThrottleModule { }
|
export class AppThrottleModule {}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,32 +1,32 @@
|
|||||||
import { Module } from "@nestjs/common";
|
import { Module } from '@nestjs/common';
|
||||||
import * as multerS3 from 'multer-s3';
|
import * as multerS3 from 'multer-s3';
|
||||||
import { S3_CLIENT, S3Module } from "../S3/S3.module";
|
import { S3_CLIENT, S3Module } from '../S3/S3.module';
|
||||||
import { DeleteAttachment } from "./DeleteAttachment";
|
import { DeleteAttachment } from './DeleteAttachment';
|
||||||
import { GetAttachment } from "./GetAttachment";
|
import { GetAttachment } from './GetAttachment';
|
||||||
import { GetAttachmentPresignedUrl } from "./GetAttachmentPresignedUrl";
|
import { GetAttachmentPresignedUrl } from './GetAttachmentPresignedUrl';
|
||||||
import { LinkAttachment } from "./LinkAttachment";
|
import { LinkAttachment } from './LinkAttachment';
|
||||||
import { UnlinkAttachment } from "./UnlinkAttachment";
|
import { UnlinkAttachment } from './UnlinkAttachment';
|
||||||
import { ValidateAttachments } from "./ValidateAttachments";
|
import { ValidateAttachments } from './ValidateAttachments';
|
||||||
import { AttachmentsOnBillPayments } from "./events/AttachmentsOnPaymentsMade";
|
import { AttachmentsOnBillPayments } from './events/AttachmentsOnPaymentsMade';
|
||||||
import { AttachmentsOnBills } from "./events/AttachmentsOnBills";
|
import { AttachmentsOnBills } from './events/AttachmentsOnBills';
|
||||||
import { AttachmentsOnCreditNote } from "./events/AttachmentsOnCreditNote";
|
import { AttachmentsOnCreditNote } from './events/AttachmentsOnCreditNote';
|
||||||
import { AttachmentsOnExpenses } from "./events/AttachmentsOnExpenses";
|
import { AttachmentsOnExpenses } from './events/AttachmentsOnExpenses';
|
||||||
import { AttachmentsOnPaymentsReceived } from "./events/AttachmentsOnPaymentsReceived";
|
import { AttachmentsOnPaymentsReceived } from './events/AttachmentsOnPaymentsReceived';
|
||||||
import { AttachmentsOnManualJournals } from "./events/AttachmentsOnManualJournals";
|
import { AttachmentsOnManualJournals } from './events/AttachmentsOnManualJournals';
|
||||||
import { AttachmentsOnVendorCredits } from "./events/AttachmentsOnVendorCredits";
|
import { AttachmentsOnVendorCredits } from './events/AttachmentsOnVendorCredits';
|
||||||
import { AttachmentsOnSaleInvoiceCreated } from "./events/AttachmentsOnSaleInvoice";
|
import { AttachmentsOnSaleInvoiceCreated } from './events/AttachmentsOnSaleInvoice';
|
||||||
import { AttachmentsOnSaleReceipt } from "./events/AttachmentsOnSaleReceipts";
|
import { AttachmentsOnSaleReceipt } from './events/AttachmentsOnSaleReceipts';
|
||||||
import { AttachmentsOnSaleEstimates } from "./events/AttachmentsOnSaleEstimates";
|
import { AttachmentsOnSaleEstimates } from './events/AttachmentsOnSaleEstimates';
|
||||||
import { AttachmentsController } from "./Attachments.controller";
|
import { AttachmentsController } from './Attachments.controller';
|
||||||
import { RegisterTenancyModel } from "../Tenancy/TenancyModels/Tenancy.module";
|
import { RegisterTenancyModel } from '../Tenancy/TenancyModels/Tenancy.module';
|
||||||
import { DocumentModel } from "./models/Document.model";
|
import { DocumentModel } from './models/Document.model';
|
||||||
import { DocumentLinkModel } from "./models/DocumentLink.model";
|
import { DocumentLinkModel } from './models/DocumentLink.model';
|
||||||
import { AttachmentsApplication } from "./AttachmentsApplication";
|
import { AttachmentsApplication } from './AttachmentsApplication';
|
||||||
import { UploadDocument } from "./UploadDocument";
|
import { UploadDocument } from './UploadDocument';
|
||||||
import { AttachmentUploadPipeline } from "./S3UploadPipeline";
|
import { AttachmentUploadPipeline } from './S3UploadPipeline';
|
||||||
import { MULTER_MODULE_OPTIONS } from "@/common/constants/files.constants";
|
import { MULTER_MODULE_OPTIONS } from '@/common/constants/files.constants';
|
||||||
import { ConfigService } from "@nestjs/config";
|
import { ConfigService } from '@nestjs/config';
|
||||||
import { S3Client } from "@aws-sdk/client-s3";
|
import { S3Client } from '@aws-sdk/client-s3';
|
||||||
|
|
||||||
const models = [
|
const models = [
|
||||||
RegisterTenancyModel(DocumentModel),
|
RegisterTenancyModel(DocumentModel),
|
||||||
@@ -71,15 +71,15 @@ const models = [
|
|||||||
key: function (req, file, cb) {
|
key: function (req, file, cb) {
|
||||||
cb(null, Date.now().toString());
|
cb(null, Date.now().toString());
|
||||||
},
|
},
|
||||||
acl: function(req, file, cb) {
|
acl: function (req, file, cb) {
|
||||||
// Conditionally set file to public or private based on isPublic flag
|
// Conditionally set file to public or private based on isPublic flag
|
||||||
const aclValue = true ? 'public-read' : 'private';
|
const aclValue = true ? 'public-read' : 'private';
|
||||||
// Set ACL based on the isPublic flag
|
// Set ACL based on the isPublic flag
|
||||||
cb(null, aclValue);
|
cb(null, aclValue);
|
||||||
}
|
},
|
||||||
}),
|
}),
|
||||||
})
|
}),
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
export class AttachmentsModule {}
|
export class AttachmentsModule {}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Transformer } from "../Transformer/Transformer";
|
import { Transformer } from '../Transformer/Transformer';
|
||||||
|
|
||||||
export class AttachmentTransformer extends Transformer {
|
export class AttachmentTransformer extends Transformer {
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Transformer } from "../Transformer/Transformer";
|
import { Transformer } from '../Transformer/Transformer';
|
||||||
|
|
||||||
export class AttachmentTransformer extends Transformer{
|
export class AttachmentTransformer extends Transformer {
|
||||||
/**
|
/**
|
||||||
* Exclude attributes.
|
* Exclude attributes.
|
||||||
* @returns {string[]}
|
* @returns {string[]}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export class GetAttachment {
|
|||||||
@Inject(S3_CLIENT)
|
@Inject(S3_CLIENT)
|
||||||
private readonly s3: S3Client,
|
private readonly s3: S3Client,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves data of the given document key.
|
* Retrieves data of the given document key.
|
||||||
* @param {string} filekey
|
* @param {string} filekey
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { S3_CLIENT } from '../S3/S3.module';
|
|||||||
export class GetAttachmentPresignedUrl {
|
export class GetAttachmentPresignedUrl {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly configService: ConfigService,
|
private readonly configService: ConfigService,
|
||||||
|
|
||||||
@Inject(DocumentModel.name)
|
@Inject(DocumentModel.name)
|
||||||
private readonly documentModel: TenantModelProxy<typeof DocumentModel>,
|
private readonly documentModel: TenantModelProxy<typeof DocumentModel>,
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ export class GetAttachmentPresignedUrl {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the presigned url of the given attachment key with the original filename.
|
* Retrieves the presigned url of the given attachment key with the original filename.
|
||||||
* @param {string} key -
|
* @param {string} key -
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
async getPresignedUrl(key: string) {
|
async getPresignedUrl(key: string) {
|
||||||
@@ -36,7 +36,9 @@ export class GetAttachmentPresignedUrl {
|
|||||||
Key: key,
|
Key: key,
|
||||||
ResponseContentDisposition,
|
ResponseContentDisposition,
|
||||||
});
|
});
|
||||||
const signedUrl = await getSignedUrl(this.s3Client, command, { expiresIn: 300 });
|
const signedUrl = await getSignedUrl(this.s3Client, command, {
|
||||||
|
expiresIn: 300,
|
||||||
|
});
|
||||||
|
|
||||||
return signedUrl;
|
return signedUrl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,7 @@ import { Injectable } from '@nestjs/common';
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AttachmentUploadPipeline {
|
export class AttachmentUploadPipeline {
|
||||||
constructor(
|
constructor(private readonly configService: ConfigService) {}
|
||||||
private readonly configService: ConfigService
|
|
||||||
) {}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Middleware to ensure that S3 configuration is properly set before proceeding.
|
* Middleware to ensure that S3 configuration is properly set before proceeding.
|
||||||
@@ -18,11 +16,7 @@ export class AttachmentUploadPipeline {
|
|||||||
public validateS3Configured(req: Request, res: Response, next: NextFunction) {
|
public validateS3Configured(req: Request, res: Response, next: NextFunction) {
|
||||||
const config = this.configService.get('s3');
|
const config = this.configService.get('s3');
|
||||||
|
|
||||||
if (
|
if (!config.region || !config.accessKeyId || !config.secretAccessKey) {
|
||||||
!config.region ||
|
|
||||||
!config.accessKeyId ||
|
|
||||||
!config.secretAccessKey
|
|
||||||
) {
|
|
||||||
const missingKeys = [];
|
const missingKeys = [];
|
||||||
if (!config.region) missingKeys.push('region');
|
if (!config.region) missingKeys.push('region');
|
||||||
if (!config.accessKeyId) missingKeys.push('accessKeyId');
|
if (!config.accessKeyId) missingKeys.push('accessKeyId');
|
||||||
|
|||||||
@@ -47,10 +47,13 @@ export class UnlinkAttachment {
|
|||||||
const foundLinkModel = await LinkModel().query(trx).findById(modelId);
|
const foundLinkModel = await LinkModel().query(trx).findById(modelId);
|
||||||
validateLinkModelEntryExists(foundLinkModel);
|
validateLinkModelEntryExists(foundLinkModel);
|
||||||
|
|
||||||
const document = await this.documentModel().query(trx).findOne('key', filekey);
|
const document = await this.documentModel()
|
||||||
|
.query(trx)
|
||||||
|
.findOne('key', filekey);
|
||||||
|
|
||||||
// Delete the document link.
|
// Delete the document link.
|
||||||
await this.documentLinkModel().query(trx)
|
await this.documentLinkModel()
|
||||||
|
.query(trx)
|
||||||
.where('modelRef', modelRef)
|
.where('modelRef', modelRef)
|
||||||
.where('modelId', modelId)
|
.where('modelId', modelId)
|
||||||
.where('documentId', document.id)
|
.where('documentId', document.id)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
export enum ERRORS {
|
export enum ERRORS {
|
||||||
DOCUMENT_LINK_REF_INVALID = 'DOCUMENT_LINK_REF_INVALID',
|
DOCUMENT_LINK_REF_INVALID = 'DOCUMENT_LINK_REF_INVALID',
|
||||||
DOCUMENT_LINK_ID_INVALID = 'DOCUMENT_LINK_ID_INVALID',
|
DOCUMENT_LINK_ID_INVALID = 'DOCUMENT_LINK_ID_INVALID',
|
||||||
DOCUMENT_LINK_ALREADY_LINKED = 'DOCUMENT_LINK_ALREADY_LINKED'
|
DOCUMENT_LINK_ALREADY_LINKED = 'DOCUMENT_LINK_ALREADY_LINKED',
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,4 +20,3 @@ export function InjectAttachable() {
|
|||||||
export function getAttachableModelsMap() {
|
export function getAttachableModelsMap() {
|
||||||
return attachableModelsMap;
|
return attachableModelsMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { ApiProperty } from "@nestjs/swagger";
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { IsNotEmpty, IsString } from "class-validator";
|
import { IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
|
||||||
|
|
||||||
export class AttachmentLinkDto {
|
export class AttachmentLinkDto {
|
||||||
@IsString()
|
@IsString()
|
||||||
@@ -8,12 +7,10 @@ export class AttachmentLinkDto {
|
|||||||
key: string;
|
key: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export class UnlinkAttachmentDto {
|
export class UnlinkAttachmentDto {
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
modelRef: string;
|
modelRef: string;
|
||||||
|
|
||||||
|
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
modelId: number;
|
modelId: number;
|
||||||
}
|
}
|
||||||
@@ -22,12 +19,11 @@ export class LinkAttachmentDto {
|
|||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
modelRef: string;
|
modelRef: string;
|
||||||
|
|
||||||
|
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
modelId: number;
|
modelId: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class UploadAttachmentDto {
|
export class UploadAttachmentDto {
|
||||||
@ApiProperty({ type: 'string', format: 'binary' })
|
@ApiProperty({ type: 'string', format: 'binary' })
|
||||||
file: any;
|
file: any;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ import { events } from '@/common/events/events';
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class AttachmentsOnBills {
|
export class AttachmentsOnBills {
|
||||||
/**
|
/**
|
||||||
* @param {LinkAttachment} linkAttachmentService
|
* @param {LinkAttachment} linkAttachmentService
|
||||||
* @param {UnlinkAttachment} unlinkAttachmentService
|
* @param {UnlinkAttachment} unlinkAttachmentService
|
||||||
* @param {ValidateAttachments} validateDocuments
|
* @param {ValidateAttachments} validateDocuments
|
||||||
*/
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
private readonly linkAttachmentService: LinkAttachment,
|
private readonly linkAttachmentService: LinkAttachment,
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ import { events } from '@/common/events/events';
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class AttachmentsOnCreditNote {
|
export class AttachmentsOnCreditNote {
|
||||||
/**
|
/**
|
||||||
* @param {LinkAttachment} linkAttachmentService -
|
* @param {LinkAttachment} linkAttachmentService -
|
||||||
* @param {UnlinkAttachment} unlinkAttachmentService -
|
* @param {UnlinkAttachment} unlinkAttachmentService -
|
||||||
* @param {ValidateAttachments} validateDocuments -
|
* @param {ValidateAttachments} validateDocuments -
|
||||||
*/
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
private readonly linkAttachmentService: LinkAttachment,
|
private readonly linkAttachmentService: LinkAttachment,
|
||||||
|
|||||||
@@ -52,12 +52,7 @@ export class AttachmentsOnExpenses {
|
|||||||
|
|
||||||
const keys = expenseDTO.attachments?.map((attachment) => attachment.key);
|
const keys = expenseDTO.attachments?.map((attachment) => attachment.key);
|
||||||
|
|
||||||
await this.linkAttachmentService.bulkLink(
|
await this.linkAttachmentService.bulkLink(keys, 'Expense', expense.id, trx);
|
||||||
keys,
|
|
||||||
'Expense',
|
|
||||||
expense.id,
|
|
||||||
trx,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export class AuthController {
|
|||||||
|
|
||||||
@Inject(TenantModel.name)
|
@Inject(TenantModel.name)
|
||||||
private readonly tenantModel: typeof TenantModel,
|
private readonly tenantModel: typeof TenantModel,
|
||||||
) { }
|
) {}
|
||||||
|
|
||||||
@Post('/signin')
|
@Post('/signin')
|
||||||
@UseGuards(LocalAuthGuard)
|
@UseGuards(LocalAuthGuard)
|
||||||
@@ -52,7 +52,8 @@ export class AuthController {
|
|||||||
@ApiBody({ type: AuthSigninDto })
|
@ApiBody({ type: AuthSigninDto })
|
||||||
@ApiResponse({
|
@ApiResponse({
|
||||||
status: 200,
|
status: 200,
|
||||||
description: 'Sign-in successful. Returns access token and tenant/organization IDs.',
|
description:
|
||||||
|
'Sign-in successful. Returns access token and tenant/organization IDs.',
|
||||||
schema: { $ref: getSchemaPath(AuthSigninResponseDto) },
|
schema: { $ref: getSchemaPath(AuthSigninResponseDto) },
|
||||||
})
|
})
|
||||||
async signin(
|
async signin(
|
||||||
@@ -73,7 +74,10 @@ export class AuthController {
|
|||||||
@Post('/signup')
|
@Post('/signup')
|
||||||
@ApiOperation({ summary: 'Sign up a new user' })
|
@ApiOperation({ summary: 'Sign up a new user' })
|
||||||
@ApiBody({ type: AuthSignupDto })
|
@ApiBody({ type: AuthSignupDto })
|
||||||
@ApiResponse({ status: 201, description: 'Sign-up initiated. Check email for confirmation.' })
|
@ApiResponse({
|
||||||
|
status: 201,
|
||||||
|
description: 'Sign-up initiated. Check email for confirmation.',
|
||||||
|
})
|
||||||
signup(@Request() req: Request, @Body() signupDto: AuthSignupDto) {
|
signup(@Request() req: Request, @Body() signupDto: AuthSignupDto) {
|
||||||
return this.authApp.signUp(signupDto);
|
return this.authApp.signUp(signupDto);
|
||||||
}
|
}
|
||||||
@@ -89,14 +93,20 @@ export class AuthController {
|
|||||||
@Post('/send_reset_password')
|
@Post('/send_reset_password')
|
||||||
@ApiOperation({ summary: 'Send reset password email' })
|
@ApiOperation({ summary: 'Send reset password email' })
|
||||||
@ApiBody({ type: AuthSendResetPasswordDto })
|
@ApiBody({ type: AuthSendResetPasswordDto })
|
||||||
@ApiResponse({ status: 200, description: 'Reset password email sent if the account exists.' })
|
@ApiResponse({
|
||||||
|
status: 200,
|
||||||
|
description: 'Reset password email sent if the account exists.',
|
||||||
|
})
|
||||||
sendResetPassword(@Body() body: AuthSendResetPasswordDto) {
|
sendResetPassword(@Body() body: AuthSendResetPasswordDto) {
|
||||||
return this.authApp.sendResetPassword(body.email);
|
return this.authApp.sendResetPassword(body.email);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('/reset_password/:token')
|
@Post('/reset_password/:token')
|
||||||
@ApiOperation({ summary: 'Reset password using token' })
|
@ApiOperation({ summary: 'Reset password using token' })
|
||||||
@ApiParam({ name: 'token', description: 'Reset password token from email link' })
|
@ApiParam({
|
||||||
|
name: 'token',
|
||||||
|
description: 'Reset password token from email link',
|
||||||
|
})
|
||||||
@ApiBody({ type: AuthResetPasswordDto })
|
@ApiBody({ type: AuthResetPasswordDto })
|
||||||
@ApiResponse({ status: 200, description: 'Password reset successfully.' })
|
@ApiResponse({ status: 200, description: 'Password reset successfully.' })
|
||||||
resetPassword(
|
resetPassword(
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ export class AuthApiKeysController {
|
|||||||
constructor(
|
constructor(
|
||||||
private readonly getApiKeysService: GetApiKeysService,
|
private readonly getApiKeysService: GetApiKeysService,
|
||||||
private readonly generateApiKeyService: GenerateApiKey,
|
private readonly generateApiKeyService: GenerateApiKey,
|
||||||
) { }
|
) {}
|
||||||
|
|
||||||
@Post('generate')
|
@Post('generate')
|
||||||
@ApiOperation({ summary: 'Generate a new API key' })
|
@ApiOperation({ summary: 'Generate a new API key' })
|
||||||
|
|||||||
@@ -41,9 +41,9 @@ export class AuthenticationMailMesssages {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sendResetPasswordMail(user: ModelObject<SystemUser>, token: string) {
|
sendResetPasswordMail(user: ModelObject<SystemUser>, token: string) {
|
||||||
const mail = this.resetPasswordMessage(user, token);
|
const mail = this.resetPasswordMessage(user, token);
|
||||||
|
|
||||||
return this.mailTransporter.send(mail);
|
return this.mailTransporter.send(mail);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -72,11 +72,7 @@ export class AuthenticationMailMesssages {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sendSignupVerificationMail(email: string, fullName: string, token: string) {
|
sendSignupVerificationMail(email: string, fullName: string, token: string) {
|
||||||
const mail = this.signupVerificationMail(
|
const mail = this.signupVerificationMail(email, fullName, token);
|
||||||
email,
|
|
||||||
fullName,
|
|
||||||
token,
|
|
||||||
);
|
|
||||||
return this.mailTransporter.send(mail);
|
return this.mailTransporter.send(mail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export class AuthedController {
|
|||||||
constructor(
|
constructor(
|
||||||
private readonly getAuthedAccountService: GetAuthenticatedAccount,
|
private readonly getAuthedAccountService: GetAuthenticatedAccount,
|
||||||
private readonly authApp: AuthenticationApplication,
|
private readonly authApp: AuthenticationApplication,
|
||||||
) { }
|
) {}
|
||||||
|
|
||||||
@Post('/signup/verify/resend')
|
@Post('/signup/verify/resend')
|
||||||
@ApiOperation({ summary: 'Resend the signup confirmation message' })
|
@ApiOperation({ summary: 'Resend the signup confirmation message' })
|
||||||
|
|||||||
@@ -24,16 +24,14 @@ export class AuthSendResetPasswordService {
|
|||||||
|
|
||||||
@Inject(SystemUser.name)
|
@Inject(SystemUser.name)
|
||||||
private readonly systemUserModel: typeof SystemUser,
|
private readonly systemUserModel: typeof SystemUser,
|
||||||
) { }
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends the given email reset password email.
|
* Sends the given email reset password email.
|
||||||
* @param {string} email - Email address.
|
* @param {string} email - Email address.
|
||||||
*/
|
*/
|
||||||
async sendResetPassword(email: string): Promise<void> {
|
async sendResetPassword(email: string): Promise<void> {
|
||||||
const user = await this.systemUserModel
|
const user = await this.systemUserModel.query().findOne({ email });
|
||||||
.query()
|
|
||||||
.findOne({ email });
|
|
||||||
|
|
||||||
if (!user) return;
|
if (!user) return;
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export class AuthSigninService {
|
|||||||
private readonly systemUserModel: typeof SystemUser,
|
private readonly systemUserModel: typeof SystemUser,
|
||||||
private readonly jwtService: JwtService,
|
private readonly jwtService: JwtService,
|
||||||
private readonly clsService: ClsService,
|
private readonly clsService: ClsService,
|
||||||
) { }
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates the given email and password.
|
* Validates the given email and password.
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export class AuthSignupService {
|
|||||||
|
|
||||||
@Inject(SystemUser.name)
|
@Inject(SystemUser.name)
|
||||||
private readonly systemUserModel: typeof SystemUser,
|
private readonly systemUserModel: typeof SystemUser,
|
||||||
) { }
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a new tenant with user from user input.
|
* Registers a new tenant with user from user input.
|
||||||
@@ -53,7 +53,7 @@ export class AuthSignupService {
|
|||||||
const verifiedEnabed = signupConfirmation.enabled ?? false;
|
const verifiedEnabed = signupConfirmation.enabled ?? false;
|
||||||
const verifyToken = verifiedEnabed ? verifyTokenCrypto : '';
|
const verifyToken = verifiedEnabed ? verifyTokenCrypto : '';
|
||||||
const verified = !verifiedEnabed;
|
const verified = !verifiedEnabed;
|
||||||
|
|
||||||
const inviteAcceptedAt = moment().format('YYYY-MM-DD');
|
const inviteAcceptedAt = moment().format('YYYY-MM-DD');
|
||||||
|
|
||||||
// Triggers signin up event.
|
// Triggers signin up event.
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export class GenerateApiKey {
|
|||||||
private readonly tenancyContext: TenancyContext,
|
private readonly tenancyContext: TenancyContext,
|
||||||
@Inject(ApiKeyModel.name)
|
@Inject(ApiKeyModel.name)
|
||||||
private readonly apiKeyModel: typeof ApiKeyModel,
|
private readonly apiKeyModel: typeof ApiKeyModel,
|
||||||
) { }
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a new secure API key for the current tenant and system user.
|
* Generates a new secure API key for the current tenant and system user.
|
||||||
|
|||||||
@@ -11,5 +11,3 @@ export class InvalidEmailPasswordException extends UnauthorizedException {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { Transformer } from '@/modules/Transformer/Transformer';
|
import { Transformer } from '@/modules/Transformer/Transformer';
|
||||||
|
|
||||||
export class GetApiKeysTransformer extends Transformer {
|
export class GetApiKeysTransformer extends Transformer {
|
||||||
|
|
||||||
public includeAttributes = (): string[] => {
|
public includeAttributes = (): string[] => {
|
||||||
return ['token'];
|
return ['token'];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,12 +4,7 @@ import { IAuthGetMetaPOJO } from '../Auth.interfaces';
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class GetAuthMetaService {
|
export class GetAuthMetaService {
|
||||||
|
constructor(private readonly configService: ConfigService) {}
|
||||||
constructor(
|
|
||||||
private readonly configService: ConfigService,
|
|
||||||
) {
|
|
||||||
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the authentication meta for SPA.
|
* Retrieves the authentication meta for SPA.
|
||||||
* @returns {Promise<IAuthGetMetaPOJO>}
|
* @returns {Promise<IAuthGetMetaPOJO>}
|
||||||
|
|||||||
@@ -22,9 +22,7 @@ export class BankRulesApplication {
|
|||||||
* @param {ICreateBankRuleDTO} createRuleDTO - Bank rule data.
|
* @param {ICreateBankRuleDTO} createRuleDTO - Bank rule data.
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
public createBankRule(
|
public createBankRule(createRuleDTO: CreateBankRuleDto): Promise<BankRule> {
|
||||||
createRuleDTO: CreateBankRuleDto,
|
|
||||||
): Promise<BankRule> {
|
|
||||||
return this.createBankRuleService.createBankRule(createRuleDTO);
|
return this.createBankRuleService.createBankRule(createRuleDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Transformer } from "@/modules/Transformer/Transformer";
|
import { Transformer } from '@/modules/Transformer/Transformer';
|
||||||
|
|
||||||
export class GetBankRuleTransformer extends Transformer {
|
export class GetBankRuleTransformer extends Transformer {
|
||||||
/**
|
/**
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user