mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-15 20:30:33 +00:00
fix issues.
This commit is contained in:
@@ -14,7 +14,6 @@ exports.up = function (knex) {
|
||||
table.text('note').nullable();
|
||||
table.integer('category_id').unsigned();
|
||||
table.integer('user_id').unsigned();
|
||||
table.string('attachment_file');
|
||||
table.timestamps();
|
||||
});
|
||||
};
|
||||
|
||||
@@ -9,7 +9,7 @@ exports.up = function (knex) {
|
||||
table.integer('view_id').unsigned();
|
||||
}).then(() => {
|
||||
return knex.seed.run({
|
||||
specific: 'seed_views_role.js',
|
||||
specific: 'seed_views_roles.js',
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@@ -7,13 +7,13 @@ exports.seed = function(knex) {
|
||||
return knex('resource_fields').insert([
|
||||
{ id: 1, label_name: 'Name', key: 'name', data_type: '', active: 1, predefined: 1 },
|
||||
{ id: 2, label_name: 'Code', key: 'code', data_type: '', active: 1, predefined: 1 },
|
||||
{ id: 3, label_name: 'Account Type', key: 'account_type_id', data_type: '', active: 1, predefined: 1 },
|
||||
{ id: 3, label_name: 'Account Type', key: 'type', data_type: '', active: 1, predefined: 1 },
|
||||
{ id: 4, label_name: 'Description', key: 'description', data_type: '', active: 1, predefined: 1 },
|
||||
{ id: 5, label_name: 'Account Normal', key: 'normal', data_type: 'string', active: 1, predefined: 1 },
|
||||
{
|
||||
id: 6,
|
||||
label_name: 'Root Account Type',
|
||||
key: 'root_account_type',
|
||||
key: 'root_type',
|
||||
data_type: 'string',
|
||||
active: 1,
|
||||
predefined: 1,
|
||||
|
||||
@@ -5,11 +5,11 @@ exports.seed = (knex) => {
|
||||
.then(() => {
|
||||
// Inserts seed entries
|
||||
return knex('view_roles').insert([
|
||||
{ id: 1, field_id: 6, comparator: 'equals', value: 'asset', view_id: 1 },
|
||||
{ id: 2, field_id: 6, comparator: 'equals', value: 'liability', view_id: 2 },
|
||||
{ id: 3, field_id: 6, comparator: 'equals', value: 'equity', view_id: 3 },
|
||||
{ id: 4, field_id: 6, comparator: 'equals', value: 'income', view_id: 4 },
|
||||
{ id: 5, field_id: 6, comparator: 'equals', value: 'expense', view_id: 5 },
|
||||
{ id: 1, field_id: 6, index: 1, comparator: 'equals', value: 'asset', view_id: 1 },
|
||||
{ id: 2, field_id: 6, index: 1, comparator: 'equals', value: 'liability', view_id: 2 },
|
||||
{ id: 3, field_id: 6, index: 1, comparator: 'equals', value: 'equity', view_id: 3 },
|
||||
{ id: 4, field_id: 6, index: 1, comparator: 'equals', value: 'income', view_id: 4 },
|
||||
{ id: 5, field_id: 6, index: 1, comparator: 'equals', value: 'expense', view_id: 5 },
|
||||
]);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -82,6 +82,7 @@ export default {
|
||||
}
|
||||
const form = {
|
||||
custom_fields: [],
|
||||
media_ids: [],
|
||||
...req.body,
|
||||
};
|
||||
const {
|
||||
@@ -90,6 +91,7 @@ export default {
|
||||
ResourceField,
|
||||
ItemCategory,
|
||||
Item,
|
||||
MediaLink,
|
||||
} = req.models;
|
||||
const errorReasons = [];
|
||||
|
||||
@@ -146,6 +148,7 @@ export default {
|
||||
return res.boom.badRequest(null, { errors: errorReasons });
|
||||
}
|
||||
|
||||
const bulkSaveMediaLinks = [];
|
||||
const item = await Item.query().insertAndFetch({
|
||||
name: form.name,
|
||||
type: form.type,
|
||||
@@ -156,6 +159,20 @@ export default {
|
||||
currency_code: form.currency_code,
|
||||
note: form.note,
|
||||
});
|
||||
|
||||
form.media_ids.forEach((mediaId) => {
|
||||
const oper = MediaLink.query().insert({
|
||||
model_name: 'Item',
|
||||
media_id: mediaId,
|
||||
model_id: item.id,
|
||||
});
|
||||
bulkSaveMediaLinks.push(oper);
|
||||
});
|
||||
|
||||
// Save the media links.
|
||||
await Promise.all([
|
||||
...bulkSaveMediaLinks,
|
||||
]);
|
||||
return res.status(200).send({ id: item.id });
|
||||
},
|
||||
},
|
||||
@@ -188,14 +205,14 @@ export default {
|
||||
code: 'validation_error', ...validationErrors,
|
||||
});
|
||||
}
|
||||
const { Account, Item, ItemCategory } = req.models;
|
||||
const { Account, Item, ItemCategory, MediaLink } = req.models;
|
||||
const { id } = req.params;
|
||||
|
||||
const form = {
|
||||
custom_fields: [],
|
||||
...req.body,
|
||||
};
|
||||
const item = await Item.query().findById(id);
|
||||
const item = await Item.query().findById(id).withGraphFetched('media');
|
||||
|
||||
if (!item) {
|
||||
return res.boom.notFound(null, {
|
||||
@@ -235,12 +252,12 @@ export default {
|
||||
if (attachment) {
|
||||
const publicPath = 'storage/app/public/';
|
||||
const tenantPath = `${publicPath}${req.organizationId}`;
|
||||
|
||||
try {
|
||||
await fsPromises.unlink(`${tenantPath}/${item.attachmentFile}`);
|
||||
} catch (error) {
|
||||
Logger.log('error', 'Delete item attachment file delete failed.', { error });
|
||||
}
|
||||
|
||||
try {
|
||||
await attachment.mv(`${tenantPath}/${attachment.md5}.png`);
|
||||
} catch (error) {
|
||||
@@ -262,6 +279,22 @@ export default {
|
||||
note: form.note,
|
||||
attachment_file: (attachment) ? item.attachmentFile : null,
|
||||
});
|
||||
|
||||
// Save links of new inserted media that associated to the item model.
|
||||
const itemMediaIds = item.media.map((m) => m.id);
|
||||
const newInsertedMedia = difference(form.media_ids, itemMediaIds);
|
||||
const bulkSaveMediaLink = [];
|
||||
|
||||
newInsertedMedia.forEach((mediaId) => {
|
||||
const oper = MediaLink.query().insert({
|
||||
model_name: 'Journal',
|
||||
model_id: manualJournal.id,
|
||||
media_id: mediaId,
|
||||
});
|
||||
bulkSaveMediaLink.push(oper);
|
||||
});
|
||||
await Promise.all([ ...newInsertedMedia ]);
|
||||
|
||||
return res.status(200).send({ id: updatedItem.id });
|
||||
},
|
||||
},
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
validationResult,
|
||||
} from 'express-validator';
|
||||
import fs from 'fs';
|
||||
import { difference } from 'lodash';
|
||||
import asyncMiddleware from '@/http/middleware/asyncMiddleware';
|
||||
import Logger from '@/services/Logger';
|
||||
|
||||
@@ -22,7 +23,7 @@ export default {
|
||||
this.upload.validation,
|
||||
asyncMiddleware(this.upload.handler));
|
||||
|
||||
router.delete('/delete/:id',
|
||||
router.delete('/',
|
||||
this.delete.validation,
|
||||
asyncMiddleware(this.delete.handler));
|
||||
|
||||
@@ -109,7 +110,8 @@ export default {
|
||||
*/
|
||||
delete: {
|
||||
validation: [
|
||||
param('id').exists().isNumeric().toInt(),
|
||||
query('ids').exists().isArray(),
|
||||
query('ids.*').exists().isNumeric().toInt(),
|
||||
],
|
||||
async handler(req, res) {
|
||||
const validationErrors = validationResult(req);
|
||||
@@ -120,26 +122,37 @@ export default {
|
||||
});
|
||||
}
|
||||
const { Media, MediaLink } = req.models;
|
||||
const { id } = req.params;
|
||||
const media = await Media.query().where('id', id).first();
|
||||
const ids = Array.isArray(req.query.ids) ? req.query.ids : [req.query.ids];
|
||||
const media = await Media.query().whereIn('id', ids);
|
||||
const mediaIds = media.map((m) => m.id);
|
||||
const notFoundMedia = difference(ids, mediaIds);
|
||||
|
||||
if (!media) {
|
||||
if (notFoundMedia.length) {
|
||||
return res.status(400).send({
|
||||
errors: [{ type: 'MEDIA.ID.NOT.FOUND', code: 200 }],
|
||||
errors: [{ type: 'MEDIA.IDS.NOT.FOUND', code: 200, ids: notFoundMedia }],
|
||||
});
|
||||
}
|
||||
const publicPath = 'storage/app/public/';
|
||||
const tenantPath = `${publicPath}${req.organizationId}`;
|
||||
const unlinkOpers = [];
|
||||
|
||||
try {
|
||||
await fsPromises.unlink(`${tenantPath}/${media.attachmentFile}`);
|
||||
Logger.log('error', 'Attachment file has been deleted.');
|
||||
} catch (error) {
|
||||
Logger.log('error', 'Delete item attachment file delete failed.', { error });
|
||||
}
|
||||
media.forEach((mediaModel) => {
|
||||
const oper = fsPromises.unlink(`${tenantPath}/${mediaModel.attachmentFile}`);
|
||||
unlinkOpers.push(oper);
|
||||
});
|
||||
await Promise.all(unlinkOpers).then((resolved) => {
|
||||
resolved.forEach(() => {
|
||||
Logger.log('error', 'Attachment file has been deleted.');
|
||||
});
|
||||
})
|
||||
.catch((errors) => {
|
||||
errors.forEach((error) => {
|
||||
Logger.log('error', 'Delete item attachment file delete failed.', { error });
|
||||
})
|
||||
});
|
||||
|
||||
await MediaLink.query().where('media_id', media.id).delete();
|
||||
await Media.query().where('id', media.id).delete();
|
||||
await MediaLink.query().whereIn('media_id', mediaIds).delete();
|
||||
await Media.query().whereIn('id', mediaIds).delete();
|
||||
|
||||
return res.status(200).send();
|
||||
},
|
||||
|
||||
@@ -12,6 +12,9 @@ export default class Item extends TenantModel {
|
||||
return 'items';
|
||||
}
|
||||
|
||||
/**
|
||||
* Model modifiers.
|
||||
*/
|
||||
static get modifiers() {
|
||||
const TABLE_NAME = Item.tableName;
|
||||
|
||||
@@ -29,6 +32,7 @@ export default class Item extends TenantModel {
|
||||
* Relationship mapping.
|
||||
*/
|
||||
static get relationMappings() {
|
||||
const Media = require('@/models/Media');
|
||||
const Account = require('@/models/Account');
|
||||
const ItemCategory = require('@/models/ItemCategory');
|
||||
|
||||
@@ -71,6 +75,19 @@ export default class Item extends TenantModel {
|
||||
to: 'accounts.id',
|
||||
},
|
||||
},
|
||||
|
||||
media: {
|
||||
relation: Model.ManyToManyRelation,
|
||||
modelClass: this.relationBindKnex(Media.default),
|
||||
join: {
|
||||
from: 'items.id',
|
||||
through: {
|
||||
from: 'media_links.model_id',
|
||||
to: 'media_links.media_id',
|
||||
},
|
||||
to: 'media.id',
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user