Skip to content

Commit

Permalink
Merge pull request #388 from bigcapitalhq/fix-import-bugs
Browse files Browse the repository at this point in the history
fix: import resources improvements
  • Loading branch information
abouolia authored Mar 27, 2024
2 parents 858e354 + ad4e51d commit fc1d123
Show file tree
Hide file tree
Showing 64 changed files with 1,633 additions and 259 deletions.
12 changes: 6 additions & 6 deletions packages/server/src/api/controllers/Accounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default class AccountsController extends BaseController {
/**
* Router constructor method.
*/
router() {
public router() {
const router = Router();

router.get(
Expand Down Expand Up @@ -98,7 +98,7 @@ export default class AccountsController extends BaseController {
/**
* Create account DTO Schema validation.
*/
get createAccountDTOSchema() {
private get createAccountDTOSchema() {
return [
check('name')
.exists()
Expand Down Expand Up @@ -131,7 +131,7 @@ export default class AccountsController extends BaseController {
/**
* Account DTO Schema validation.
*/
get editAccountDTOSchema() {
private get editAccountDTOSchema() {
return [
check('name')
.exists()
Expand Down Expand Up @@ -160,14 +160,14 @@ export default class AccountsController extends BaseController {
];
}

get accountParamSchema() {
private get accountParamSchema() {
return [param('id').exists().isNumeric().toInt()];
}

/**
* Accounts list validation schema.
*/
get accountsListSchema() {
private get accountsListSchema() {
return [
query('view_slug').optional({ nullable: true }).isString().trim(),
query('stringified_filter_roles').optional().isJSON(),
Expand Down Expand Up @@ -349,7 +349,7 @@ export default class AccountsController extends BaseController {
// Filter query.
const filter = {
sortOrder: 'desc',
columnSortBy: 'created_at',
columnSortBy: 'createdAt',
inactiveMode: false,
structure: IAccountsStructureType.Tree,
...this.matchedQueryData(req),
Expand Down
6 changes: 2 additions & 4 deletions packages/server/src/api/controllers/Contacts/Customers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,8 @@ export default class CustomersController extends ContactsController {
try {
const contact = await this.customersApplication.createCustomer(
tenantId,
contactDTO,
user
contactDTO
);

return res.status(200).send({
id: contact.id,
message: 'The customer has been created successfully.',
Expand Down Expand Up @@ -291,7 +289,7 @@ export default class CustomersController extends ContactsController {
const filter = {
inactiveMode: false,
sortOrder: 'desc',
columnSortBy: 'created_at',
columnSortBy: 'createdAt',
page: 1,
pageSize: 12,
...this.matchedQueryData(req),
Expand Down
2 changes: 1 addition & 1 deletion packages/server/src/api/controllers/Contacts/Vendors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ export default class VendorsController extends ContactsController {
const vendorsFilter: IVendorsFilter = {
inactiveMode: false,
sortOrder: 'desc',
columnSortBy: 'created_at',
columnSortBy: 'createdAt',
page: 1,
pageSize: 12,
...this.matchedQueryData(req),
Expand Down
76 changes: 72 additions & 4 deletions packages/server/src/api/controllers/Import/ImportController.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { Inject, Service } from 'typedi';
import { Router, Request, Response, NextFunction } from 'express';
import { body, param } from 'express-validator';
import { body, param, query } from 'express-validator';
import { defaultTo } from 'lodash';
import BaseController from '@/api/controllers/BaseController';
import { ServiceError } from '@/exceptions';
import { ImportResourceApplication } from '@/services/Import/ImportResourceApplication';
import { uploadImportFile } from './_utils';
import { parseJsonSafe } from '@/utils/parse-json-safe';

@Service()
export class ImportController extends BaseController {
Expand Down Expand Up @@ -42,6 +44,17 @@ export class ImportController extends BaseController {
this.asyncMiddleware(this.mapping.bind(this)),
this.catchServiceErrors
);
router.get(
'/sample',
[query('resource').exists(), query('format').optional()],
this.downloadImportSample.bind(this),
this.catchServiceErrors
);
router.get(
'/:import_id',
this.asyncMiddleware(this.getImportFileMeta.bind(this)),
this.catchServiceErrors
);
router.get(
'/:import_id/preview',
this.asyncMiddleware(this.preview.bind(this)),
Expand All @@ -55,7 +68,7 @@ export class ImportController extends BaseController {
* @returns {ValidationSchema[]}
*/
private get importValidationSchema() {
return [body('resource').exists()];
return [body('resource').exists(), body('params').optional()];
}

/**
Expand All @@ -66,12 +79,15 @@ export class ImportController extends BaseController {
*/
private async fileUpload(req: Request, res: Response, next: NextFunction) {
const { tenantId } = req;
const body = this.matchedBodyData(req);
const params = defaultTo(parseJsonSafe(body.params), {});

try {
const data = await this.importResourceApp.import(
tenantId,
req.body.resource,
req.file.filename
body.resource,
req.file.filename,
params
);
return res.status(200).send(data);
} catch (error) {
Expand Down Expand Up @@ -140,6 +156,54 @@ export class ImportController extends BaseController {
}
}

/**
* Retrieves the csv/xlsx sample sheet of the given resource name.
* @param {Request} req
* @param {Response} res
* @param {NextFunction} next
*/
private async downloadImportSample(
req: Request,
res: Response,
next: NextFunction
) {
const { tenantId } = req;
const { format, resource } = this.matchedQueryData(req);

try {
const result = this.importResourceApp.sample(tenantId, resource, format);

return res.status(200).send(result);
} catch (error) {
next(error);
}
}

/**
* Retrieves the import file meta.
* @param {Request} req
* @param {Response} res
* @param {NextFunction} next
*/
private async getImportFileMeta(
req: Request,
res: Response,
next: NextFunction
) {
const { tenantId } = req;
const { import_id: importId } = req.params;

try {
const result = await this.importResourceApp.importMeta(
tenantId,
importId
);
return res.status(200).send(result);
} catch (error) {
next(error);
}
}

/**
* Transforms service errors to response.
* @param {Error}
Expand Down Expand Up @@ -174,7 +238,11 @@ export class ImportController extends BaseController {
errors: [{ type: 'IMPORTED_FILE_EXTENSION_INVALID' }],
});
}
return res.status(400).send({
errors: [{ type: error.errorType }],
});
}

next(error);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ exports.up = function (knex) {
table.string('resource');
table.json('columns');
table.json('mapping');
table.json('params');
table.timestamps();
});
};
Expand Down
3 changes: 3 additions & 0 deletions packages/server/src/interfaces/Model.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

export interface IModel {
name: string;
tableName: string;
Expand Down Expand Up @@ -35,6 +36,8 @@ export interface IModelMetaFieldCommon {
fieldType: IModelColumnType;
customQuery?: Function;
required?: boolean;
importHint?: string;
order?: number;
}

export interface IModelMetaFieldNumber {
Expand Down
15 changes: 13 additions & 2 deletions packages/server/src/models/Account.Settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@ export default {
unique: true,
required: true,
importable: true,
exportable: true,
order: 1,
},
description: {
name: 'account.field.description',
column: 'description',
fieldType: 'text',
importable: true,
exportable: true,
},
slug: {
name: 'account.field.slug',
Expand All @@ -34,9 +37,11 @@ export default {
name: 'account.field.code',
column: 'code',
fieldType: 'text',
exportable: true,
importable: true,
minLength: 3,
maxLength: 6,
importHint: 'Unique number to identify the account.',
},
rootType: {
name: 'account.field.root_type',
Expand Down Expand Up @@ -73,38 +78,44 @@ export default {
})),
required: true,
importable: true,
exportable: true,
order: 2,
},
active: {
name: 'account.field.active',
column: 'active',
fieldType: 'boolean',
filterable: false,
exportable: true,
importable: true,
},
openingBalance: {
balance: {
name: 'account.field.balance',
column: 'amount',
fieldType: 'number',
importable: true,
importable: false,
},
currencyCode: {
name: 'account.field.currency',
column: 'currency_code',
fieldType: 'text',
filterable: false,
importable: true,
exportable: true,
},
parentAccount: {
name: 'account.field.parent_account',
column: 'parent_account_id',
fieldType: 'relation',
to: { model: 'Account', to: 'id' },
importable: false,
},
createdAt: {
name: 'account.field.created_at',
column: 'created_at',
fieldType: 'date',
importable: false,
exportable: true,
},
},
};
Expand Down
Loading

0 comments on commit fc1d123

Please sign in to comment.