mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-18 05:40:31 +00:00
feat: rewrite repositories with base entity repository class.
feat: sales and purchases status. feat: sales and purchases auto-increment number. fix: settings find query with extra columns.
This commit is contained in:
@@ -1,124 +1,28 @@
|
||||
import { Account } from 'models';
|
||||
import TenantRepository from 'repositories/TenantRepository';
|
||||
import { IAccount } from 'interfaces';
|
||||
|
||||
export default class AccountRepository extends TenantRepository {
|
||||
/**
|
||||
* Constructor method.
|
||||
*/
|
||||
constructor(knex, cache) {
|
||||
super(knex, cache);
|
||||
this.model = Account;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve accounts dependency graph.
|
||||
* @returns {}
|
||||
*/
|
||||
async getDependencyGraph() {
|
||||
const { Account } = this.models;
|
||||
const accounts = await this.allAccounts();
|
||||
const cacheKey = this.getCacheKey('accounts.depGraph');
|
||||
async getDependencyGraph(withRelation) {
|
||||
const accounts = await this.all(withRelation);
|
||||
const cacheKey = this.getCacheKey('accounts.depGraph', withRelation);
|
||||
|
||||
return this.cache.get(cacheKey, async () => {
|
||||
return Account.toDependencyGraph(accounts);
|
||||
return this.model.toDependencyGraph(accounts);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all accounts on the storage.
|
||||
* @return {IAccount[]}
|
||||
*/
|
||||
allAccounts(withRelations?: string|string[]): IAccount[] {
|
||||
const { Account } = this.models;
|
||||
const cacheKey = this.getCacheKey('accounts.depGraph', withRelations);
|
||||
|
||||
return this.cache.get(cacheKey, async () => {
|
||||
return Account.query()
|
||||
.withGraphFetched(withRelations);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve account of the given account slug.
|
||||
* @param {string} slug
|
||||
* @return {IAccount}
|
||||
*/
|
||||
getBySlug(slug: string): IAccount {
|
||||
const { Account } = this.models;
|
||||
const cacheKey = this.getCacheKey('accounts.slug', slug);
|
||||
|
||||
return this.cache.get(cacheKey, () => {
|
||||
return Account.query().findOne('slug', slug);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the account by the given id.
|
||||
* @param {number} id - Account id.
|
||||
* @return {IAccount}
|
||||
*/
|
||||
findById(id: number): IAccount {
|
||||
const { Account } = this.models;
|
||||
const cacheKey = this.getCacheKey('accounts.id', id);
|
||||
|
||||
return this.cache.get(cacheKey, () => {
|
||||
return Account.query().findById(id);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve accounts by the given ids.
|
||||
* @param {number[]} ids -
|
||||
* @return {IAccount[]}
|
||||
*/
|
||||
findByIds(accountsIds: number[]) {
|
||||
const { Account } = this.models;
|
||||
const cacheKey = this.getCacheKey('accounts.id', accountsIds);
|
||||
|
||||
return this.cache.get(cacheKey, () => {
|
||||
return Account.query().whereIn('id', accountsIds);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate the given account.
|
||||
* @param {number} accountId -
|
||||
* @return {void}
|
||||
*/
|
||||
async activate(accountId: number): Promise<void> {
|
||||
const { Account } = this.models;
|
||||
await Account.query().findById(accountId).patch({ active: 1 })
|
||||
this.flushCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a new accounts to the storage.
|
||||
* @param {IAccount} account
|
||||
*/
|
||||
async insert(accountInput: IAccount): Promise<void> {
|
||||
const { Account } = this.models;
|
||||
const account = await Account.query().insertAndFetch({ ...accountInput });
|
||||
this.flushCache();
|
||||
|
||||
return account;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates account of the given account.
|
||||
* @param {number} accountId - Account id.
|
||||
* @param {IAccount} account
|
||||
* @return {void}
|
||||
*/
|
||||
async edit(accountId: number, accountInput: IAccount): Promise<void> {
|
||||
const { Account } = this.models;
|
||||
const account = await Account.query().patchAndFetchById(accountId, { ...accountInput });
|
||||
this.flushCache();
|
||||
|
||||
return account;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the given account by id.
|
||||
* @param {number} accountId - Account id.
|
||||
*/
|
||||
async deleteById(accountId: number): Promise<void> {
|
||||
const { Account } = this.models;
|
||||
await Account.query().deleteById(accountId);
|
||||
this.flushCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes account balance.
|
||||
* @param {number} accountId
|
||||
@@ -126,17 +30,9 @@ export default class AccountRepository extends TenantRepository {
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
async balanceChange(accountId: number, amount: number): Promise<void> {
|
||||
const { Account } = this.models;
|
||||
const method: string = (amount < 0) ? 'decrement' : 'increment';
|
||||
|
||||
await Account.query().where('id', accountId)[method]('amount', amount);
|
||||
await this.model.query().where('id', accountId)[method]('amount', amount);
|
||||
this.flushCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush repository cache.
|
||||
*/
|
||||
flushCache(): void {
|
||||
this.cache.delStartWith(this.repositoryName);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,4 @@
|
||||
|
||||
import { QueryBuilder } from 'knex';
|
||||
import { AccountTransaction } from 'models';
|
||||
import hashObject from 'object-hash';
|
||||
import TenantRepository from 'repositories/TenantRepository';
|
||||
|
||||
|
||||
@@ -17,13 +14,19 @@ interface IJournalTransactionsFilter {
|
||||
};
|
||||
|
||||
export default class AccountTransactionsRepository extends TenantRepository {
|
||||
/**
|
||||
* Constructor method.
|
||||
*/
|
||||
constructor(knex, cache) {
|
||||
super(knex, cache);
|
||||
this.model = AccountTransaction;
|
||||
}
|
||||
|
||||
journal(filter: IJournalTransactionsFilter) {
|
||||
const { AccountTransaction } = this.models;
|
||||
const cacheKey = this.getCacheKey('transactions.journal', filter);
|
||||
|
||||
return this.cache.get(cacheKey, () => {
|
||||
return AccountTransaction.query()
|
||||
return this.model.query()
|
||||
.modify('filterAccounts', filter.accountsIds)
|
||||
.modify('filterDateRange', filter.fromDate, filter.toDate)
|
||||
.withGraphFetched('account.type')
|
||||
|
||||
@@ -1,81 +1,49 @@
|
||||
import TenantRepository from 'repositories/TenantRepository';
|
||||
import { IAccountType } from 'interfaces';
|
||||
import { AccountType } from 'models';
|
||||
|
||||
export default class AccountTypeRepository extends TenantRepository {
|
||||
/**
|
||||
* Retrieve all accounts types.
|
||||
* @return {IAccountType[]}
|
||||
* Constructor method.
|
||||
*/
|
||||
all() {
|
||||
const { AccountType } = this.models;
|
||||
return this.cache.get('accountType.all', () => {
|
||||
return AccountType.query();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve account type meta.
|
||||
* @param {number} accountTypeId
|
||||
* @return {IAccountType}
|
||||
*/
|
||||
getTypeMeta(accountTypeId: number): IAccountType {
|
||||
const { AccountType } = this.models;
|
||||
return this.cache.get(`accountType.id.${accountTypeId}`, () => {
|
||||
return AccountType.query().findById(accountTypeId);
|
||||
});
|
||||
constructor(knex, cache) {
|
||||
super(knex, cache);
|
||||
this.model = AccountType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve accounts types of the given keys.
|
||||
* @param {string[]} keys
|
||||
* @return {IAccountType[]}
|
||||
* @return {Promise<IAccountType[]>}
|
||||
*/
|
||||
getByKeys(keys: string[]): IAccountType[] {
|
||||
const { AccountType } = this.models;
|
||||
return this.cache.get(`accountType.keys.${keys.join(',')}`, () => {
|
||||
return AccountType.query().whereIn('key', keys);
|
||||
});
|
||||
getByKeys(keys: string[]): Promise<IAccountType[]> {
|
||||
return super.findWhereIn('key', keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve account tpy eof the given key.
|
||||
* @param {string} key
|
||||
* @return {IAccountType}
|
||||
* @return {Promise<IAccountType>}
|
||||
*/
|
||||
getByKey(key: string): IAccountType {
|
||||
const { AccountType } = this.models;
|
||||
return this.cache.get(`accountType.key.${key}`, () => {
|
||||
return AccountType.query().findOne('key', key);
|
||||
});
|
||||
getByKey(key: string): Promise<IAccountType> {
|
||||
return super.findOne({ key });
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve accounts types of the given root type.
|
||||
* @param {string} rootType
|
||||
* @return {IAccountType[]}
|
||||
* @return {Promise<IAccountType[]>}
|
||||
*/
|
||||
getByRootType(rootType: string): Promise<IAccountType[]> {
|
||||
const { AccountType } = this.models;
|
||||
return this.cache.get(`accountType.rootType.${rootType}`, () => {
|
||||
return AccountType.query().where('root_type', rootType);
|
||||
});
|
||||
return super.find({ root_type: rootType });
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve accounts types of the given child type.
|
||||
* @param {string} childType
|
||||
* @return {Promise<IAccountType[]>}
|
||||
*/
|
||||
getByChildType(childType: string): Promise<IAccountType[]> {
|
||||
const { AccountType } = this.models;
|
||||
return this.cache.get(`accountType.childType.${childType}`, () => {
|
||||
return AccountType.query().where('child_type', childType);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush repository cache.
|
||||
*/
|
||||
flushCache() {
|
||||
this.cache.delStartWith('accountType');
|
||||
return super.find({ child_type: childType });
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,4 @@
|
||||
|
||||
export default class BaseModelRepository {
|
||||
|
||||
isExists(modelIdOrArray) {
|
||||
const ids = Array.isArray(modelIdOrArray) ? modelIdOrArray : [modelIdOrArray];
|
||||
const foundModels = this.model.tenant().query().whereIn('id', ids);
|
||||
|
||||
return foundModels.length > 0;
|
||||
}
|
||||
}
|
||||
12
server/src/repositories/BillRepository.ts
Normal file
12
server/src/repositories/BillRepository.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Bill } from 'models';
|
||||
import TenantRepository from 'repositories/TenantRepository';
|
||||
|
||||
export default class BillRepository extends TenantRepository {
|
||||
/**
|
||||
* Constructor method.
|
||||
*/
|
||||
constructor(knex, cache) {
|
||||
super(knex, cache);
|
||||
this.model = Bill;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,20 @@
|
||||
import hashObject from 'object-hash';
|
||||
import EntityRepository from './EntityRepository';
|
||||
|
||||
|
||||
export default class CachableRepository {
|
||||
export default class CachableRepository extends EntityRepository{
|
||||
repositoryName: string;
|
||||
|
||||
cache: any;
|
||||
|
||||
/**
|
||||
* Constructor method.
|
||||
* @param {Knex} knex
|
||||
* @param {Cache} cache
|
||||
*/
|
||||
constructor(knex, cache) {
|
||||
super(knex);
|
||||
this.cache = cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the cache key of the method name and arguments.
|
||||
* @param {string} method
|
||||
@@ -16,4 +27,197 @@ export default class CachableRepository {
|
||||
|
||||
return `${repositoryName}-${method}-${hashArgs}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all entries with specified relations.
|
||||
* @param withRelations
|
||||
*/
|
||||
all(withRelations?) {
|
||||
const cacheKey = this.getCacheKey('all', withRelations);
|
||||
|
||||
return this.cache.get(cacheKey, () => {
|
||||
return super.all(withRelations);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds list of entities with specified attributes
|
||||
* @param {Object} attributeValues - values to filter retrieved entities by
|
||||
* @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve.
|
||||
* @returns {Promise<Object[]>} - query builder. You can chain additional methods to it or call "await" or then() on it to execute
|
||||
*/
|
||||
find(attributeValues = {}, withRelations?) {
|
||||
const cacheKey = this.getCacheKey('find', attributeValues, withRelations);
|
||||
|
||||
return this.cache.get(cacheKey, () => {
|
||||
return super.find(attributeValues, withRelations);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds list of entities with attribute values that are different from specified ones
|
||||
* @param {Object} attributeValues - values to filter retrieved entities by
|
||||
* @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve, as defined in model relationMappings()
|
||||
* @returns {Promise<Object[]>} - query builder. You can chain additional methods to it or call "await" or then() on it to execute
|
||||
*/
|
||||
findWhereNot(attributeValues = {}, withRelations?) {
|
||||
const cacheKey = this.getCacheKey('findWhereNot', attributeValues, withRelations);
|
||||
|
||||
return this.cache.get(cacheKey, () => {
|
||||
return super.findWhereNot(attributeValues, withRelations);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds list of entities with specified attributes (any of multiple specified values)
|
||||
* Supports both ('attrName', ['value1', 'value2]) and ({attrName: ['value1', 'value2']} formats)
|
||||
*
|
||||
* @param {string|Object} searchParam - attribute name or search criteria object
|
||||
* @param {*[]} [attributeValues] - attribute values to filter retrieved entities by
|
||||
* @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve, as defined in model relationMappings()
|
||||
* @returns {PromiseLike<Object[]>} - query builder. You can chain additional methods to it or call "await" or then() on it to execute
|
||||
*/
|
||||
findWhereIn(searchParam, attributeValues, withRelations?) {
|
||||
const cacheKey = this.getCacheKey('findWhereIn', attributeValues, withRelations);
|
||||
|
||||
return this.cache.get(cacheKey, () => {
|
||||
return super.findWhereIn(searchParam, attributeValues, withRelations);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds first entity by given parameters
|
||||
*
|
||||
* @param {Object} attributeValues - values to filter retrieved entities by
|
||||
* @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve, as defined in model relationMappings()
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
findOne(attributeValues = {}, withRelations?) {
|
||||
const cacheKey = this.getCacheKey('findOne', attributeValues, withRelations);
|
||||
|
||||
return this.cache.get(cacheKey, () => {
|
||||
return super.findOne(attributeValues, withRelations);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds first entity by given parameters
|
||||
*
|
||||
* @param {string || number} id - value of id column of the entity
|
||||
* @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve, as defined in model relationMappings()
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
findOneById(id, withRelations?) {
|
||||
const cacheKey = this.getCacheKey('findOneById', id, withRelations);
|
||||
|
||||
return this.cache.get(cacheKey, () => {
|
||||
return super.findOneById(id, withRelations);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Persists new entity or an array of entities.
|
||||
* This method does not recursively persist related entities, use createRecursively (to be implemented) for that.
|
||||
* Batch insert only works on PostgreSQL
|
||||
* @param {Object} entity - model instance or parameters for a new entity
|
||||
* @returns {Promise<Object>} - query builder. You can chain additional methods to it or call "await" or then() on it to execute
|
||||
*/
|
||||
async create(entity) {
|
||||
const result = await super.create(entity);
|
||||
|
||||
// Flushes the repository cache after insert operation.
|
||||
this.flushCache();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Persists updated entity. If previously set fields are not present, performs an incremental update (does not remove fields unless explicitly set to null)
|
||||
*
|
||||
* @param {Object} entity - single entity instance
|
||||
* @param {Object} [trx] - knex transaction instance. If not specified, new implicit transaction will be used.
|
||||
* @returns {Promise<integer>} number of affected rows
|
||||
*/
|
||||
async update(entity, whereAttributes?) {
|
||||
const result = await super.update(entity, whereAttributes);
|
||||
|
||||
// Flushes the repository cache after update operation.
|
||||
this.flushCache();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} attributeValues - values to filter deleted entities by
|
||||
* @param {Object} [trx]
|
||||
* @returns {Promise<integer>} Query builder. After promise is resolved, returns count of deleted rows
|
||||
*/
|
||||
async deleteBy(attributeValues) {
|
||||
const result = await super.deleteBy(attributeValues);
|
||||
this.flushCache();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string || number} id - value of id column of the entity
|
||||
* @returns {Promise<integer>} Query builder. After promise is resolved, returns count of deleted rows
|
||||
*/
|
||||
deleteById(id: number|string) {
|
||||
const result = super.deleteById(id);
|
||||
|
||||
// Flushes the repository cache after insert operation.
|
||||
this.flushCache();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string|number[]} values -
|
||||
*/
|
||||
async deleteWhereIn(values: string | number[]) {
|
||||
const result = await super.deleteWhereIdIn(values);
|
||||
|
||||
// Flushes the repository cache after delete operation.
|
||||
this.flushCache();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param graph
|
||||
* @param options
|
||||
*/
|
||||
async upsertGraph(graph, options) {
|
||||
const result = await super.upsertGraph(graph, options);
|
||||
|
||||
// Flushes the repository cache after insert operation.
|
||||
this.flushCache();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {} whereAttributes
|
||||
* @param {string} field
|
||||
* @param {number} amount
|
||||
*/
|
||||
async changeNumber(whereAttributes, field: string, amount: number) {
|
||||
const result = await super.changeNumber(whereAttributes, field, amount);
|
||||
|
||||
// Flushes the repository cache after update operation.
|
||||
this.flushCache();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush repository cache.
|
||||
*/
|
||||
flushCache(): void {
|
||||
this.cache.delStartWith(this.repositoryName);
|
||||
}
|
||||
}
|
||||
@@ -1,76 +1,13 @@
|
||||
import TenantRepository from 'repositories/TenantRepository';
|
||||
import { IContact } from 'interfaces';
|
||||
import { Contact } from 'models'
|
||||
|
||||
|
||||
export default class ContactRepository extends TenantRepository {
|
||||
/**
|
||||
* Retrieve the given contact model.
|
||||
* @param {number} contactId
|
||||
*/
|
||||
findById(contactId: number): IContact {
|
||||
const { Contact } = this.models;
|
||||
return this.cache.get(`contacts.id.${contactId}`, () => {
|
||||
return Contact.query().findById(contactId);
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the given contacts model.
|
||||
* @param {number[]} contactIds - Contacts ids.
|
||||
* Constructor method.
|
||||
*/
|
||||
findByIds(contactIds: number[]): IContact[] {
|
||||
const { Contact } = this.models;
|
||||
return this.cache.get(`contacts.ids.${contactIds.join(',')}`, () => {
|
||||
return Contact.query().whereIn('id', contactIds);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a new contact model.
|
||||
* @param contact
|
||||
*/
|
||||
async insert(contactInput: IContact) {
|
||||
const { Contact } = this.models;
|
||||
const contact = await Contact.query().insert({ ...contactInput })
|
||||
this.flushCache();
|
||||
return contact;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the contact details.
|
||||
* @param {number} contactId - Contact id.
|
||||
* @param {IContact} contact - Contact input.
|
||||
*/
|
||||
async update(contactId: number, contact: IContact) {
|
||||
const { Contact } = this.models;
|
||||
await Contact.query().findById(contactId).patch({ ...contact });
|
||||
this.flushCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes contact of the given id.
|
||||
* @param {number} contactId -
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
async deleteById(contactId: number): Promise<void> {
|
||||
const { Contact } = this.models;
|
||||
await Contact.query().where('id', contactId).delete();
|
||||
this.flushCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes contacts in bulk.
|
||||
* @param {number[]} contactsIds
|
||||
*/
|
||||
async bulkDelete(contactsIds: number[]) {
|
||||
const { Contact } = this.models;
|
||||
await Contact.query().whereIn('id', contactsIds);
|
||||
this.flushCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush contact repository cache.
|
||||
*/
|
||||
flushCache() {
|
||||
this.cache.delStartWith(`contacts`);
|
||||
constructor(knex, cache) {
|
||||
super(knex, cache);
|
||||
this.model = Contact;
|
||||
}
|
||||
}
|
||||
@@ -1,75 +1,16 @@
|
||||
import TenantRepository from "./TenantRepository";
|
||||
|
||||
import { Customer } from 'models'
|
||||
export default class CustomerRepository extends TenantRepository {
|
||||
all() {
|
||||
const { Contact } = this.models;
|
||||
|
||||
return this.cache.get('customers', () => {
|
||||
return Contact.query().modify('customer');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve customer details of the given id.
|
||||
* @param {number} customerId - Customer id.
|
||||
* Constructor method.
|
||||
*/
|
||||
getById(customerId: number) {
|
||||
const { Contact } = this.models;
|
||||
|
||||
return this.cache.get(`customers.id.${customerId}`, () => {
|
||||
return Contact.query().modifier('customer').findById(customerId);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Detarmines the given customer exists.
|
||||
* @param {number} customerId
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isExists(customerId: number) {
|
||||
return !!this.getById(customerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the sales invoices that assocaited to the given customer.
|
||||
* @param {number} customerId
|
||||
*/
|
||||
getSalesInvoices(customerId: number) {
|
||||
const { SaleInvoice } = this.models;
|
||||
|
||||
return this.cache.get(`customers.invoices.${customerId}`, () => {
|
||||
return SaleInvoice.query().where('customer_id', customerId);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve customers details of the given ids.
|
||||
* @param {number[]} customersIds - Customers ids.
|
||||
* @return {IContact[]}
|
||||
*/
|
||||
customers(customersIds: number[]) {
|
||||
const { Contact } = this.models;
|
||||
return Contact.query().modifier('customer').whereIn('id', customersIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve customers of the given ids with associated sales invoices.
|
||||
* @param {number[]} customersIds - Customers ids.
|
||||
*/
|
||||
customersWithSalesInvoices(customersIds: number[]) {
|
||||
const { Contact } = this.models;
|
||||
return Contact.query().modify('customer')
|
||||
.whereIn('id', customersIds)
|
||||
.withGraphFetched('salesInvoices');
|
||||
constructor(knex, cache) {
|
||||
super(knex, cache);
|
||||
this.model = Customer;
|
||||
}
|
||||
|
||||
changeBalance(vendorId: number, amount: number) {
|
||||
const { Contact } = this.models;
|
||||
const changeMethod = (amount > 0) ? 'increment' : 'decrement';
|
||||
|
||||
return Contact.query()
|
||||
.where('id', vendorId)
|
||||
[changeMethod]('balance', Math.abs(amount));
|
||||
return super.changeNumber({ id: vendorId }, 'balance', amount);
|
||||
}
|
||||
|
||||
async changeDiffBalance(
|
||||
|
||||
231
server/src/repositories/EntityRepository.ts
Normal file
231
server/src/repositories/EntityRepository.ts
Normal file
@@ -0,0 +1,231 @@
|
||||
import { cloneDeep, cloneDeepWith, forOwn, isString } from 'lodash';
|
||||
import ModelEntityNotFound from 'exceptions/ModelEntityNotFound';
|
||||
|
||||
export default class EntityRepository {
|
||||
modelInstance: any;
|
||||
idColumn: string;
|
||||
knex: any;
|
||||
|
||||
/**
|
||||
* Constructor method.
|
||||
* @param {Knex} knex
|
||||
*/
|
||||
constructor(knex) {
|
||||
this.knex = knex;
|
||||
this.idColumn = 'id';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the model to the repository and bind it to knex instance.
|
||||
*/
|
||||
set model(model) {
|
||||
if (!this.modelInstance) {
|
||||
this.modelInstance = model.bindKnex(this.knex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the repository model binded it to knex instance.
|
||||
*/
|
||||
get model() {
|
||||
return this.modelInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all entries with specified relations.
|
||||
*
|
||||
* @param withRelations
|
||||
*/
|
||||
all(withRelations?) {
|
||||
return this.model.query().withGraphFetched(withRelations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds list of entities with specified attributes
|
||||
*
|
||||
* @param {Object} attributeValues - values to filter retrieved entities by
|
||||
* @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve.
|
||||
* @returns {Promise<Object[]>} - query builder. You can chain additional methods to it or call "await" or then() on it to execute
|
||||
*/
|
||||
find(attributeValues = {}, withRelations?) {
|
||||
return this.model
|
||||
.query()
|
||||
.where(attributeValues)
|
||||
.withGraphFetched(withRelations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds list of entities with attribute values that are different from specified ones
|
||||
*
|
||||
* @param {Object} attributeValues - values to filter retrieved entities by
|
||||
* @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve, as defined in model relationMappings()
|
||||
* @returns {PromiseLike<Object[]>} - query builder. You can chain additional methods to it or call "await" or then() on it to execute
|
||||
*/
|
||||
findWhereNot(attributeValues = {}, withRelations?) {
|
||||
return this.model
|
||||
.query()
|
||||
.whereNot(attributeValues)
|
||||
.withGraphFetched(withRelations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds list of entities with specified attributes (any of multiple specified values)
|
||||
* Supports both ('attrName', ['value1', 'value2]) and ({attrName: ['value1', 'value2']} formats)
|
||||
*
|
||||
* @param {string|Object} searchParam - attribute name or search criteria object
|
||||
* @param {*[]} [attributeValues] - attribute values to filter retrieved entities by
|
||||
* @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve, as defined in model relationMappings()
|
||||
* @returns {PromiseLike<Object[]>} - query builder. You can chain additional methods to it or call "await" or then() on it to execute
|
||||
*/
|
||||
findWhereIn(searchParam, attributeValues, withRelations?) {
|
||||
if (isString(searchParam)) {
|
||||
return this.model
|
||||
.query()
|
||||
.whereIn(searchParam, attributeValues)
|
||||
.withGraphFetched(withRelations);
|
||||
} else {
|
||||
const builder = this.model.query(this.knex).withGraphFetched(withRelations);
|
||||
forOwn(searchParam, (value, key) => {
|
||||
if (Array.isArray(value)) {
|
||||
builder.whereIn(key, value);
|
||||
} else {
|
||||
builder.where(key, value);
|
||||
}
|
||||
});
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds first entity by given parameters
|
||||
*
|
||||
* @param {Object} attributeValues - values to filter retrieved entities by
|
||||
* @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve, as defined in model relationMappings()
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
async findOne(attributeValues = {}, withRelations?) {
|
||||
const results = await this.find(attributeValues, withRelations);
|
||||
return results[0] || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds first entity by given parameters
|
||||
*
|
||||
* @param {string || number} id - value of id column of the entity
|
||||
* @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve, as defined in model relationMappings()
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
findOneById(id, withRelations?) {
|
||||
return this.findOne({ [this.idColumn]: id }, withRelations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Persists new entity or an array of entities.
|
||||
* This method does not recursively persist related entities, use createRecursively (to be implemented) for that.
|
||||
* Batch insert only works on PostgreSQL
|
||||
*
|
||||
* @param {Object} entity - model instance or parameters for a new entity
|
||||
* @returns {Promise<Object>} - query builder. You can chain additional methods to it or call "await" or then() on it to execute
|
||||
*/
|
||||
create(entity) {
|
||||
// Keep the input parameter immutable
|
||||
const instanceDTO = cloneDeep(entity);
|
||||
|
||||
return this.model.query().insert(instanceDTO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Persists updated entity. If previously set fields are not present, performs an incremental update (does not remove fields unless explicitly set to null)
|
||||
*
|
||||
* @param {Object} entity - single entity instance
|
||||
* @returns {Promise<integer>} number of affected rows
|
||||
*/
|
||||
async update(entity, whereAttributes?) {
|
||||
const entityDto = cloneDeep(entity);
|
||||
const identityClause = {};
|
||||
|
||||
if (Array.isArray(this.idColumn)) {
|
||||
this.idColumn.forEach((idColumn) => (identityClause[idColumn] = entityDto[idColumn]));
|
||||
} else {
|
||||
identityClause[this.idColumn] = entityDto[this.idColumn];
|
||||
}
|
||||
const whereConditions = (whereAttributes || identityClause);
|
||||
const modifiedEntitiesCount = await this.model
|
||||
.query()
|
||||
.where(whereConditions)
|
||||
.update(entityDto);
|
||||
|
||||
if (modifiedEntitiesCount === 0) {
|
||||
throw new ModelEntityNotFound(entityDto[this.idColumn]);
|
||||
}
|
||||
return modifiedEntitiesCount;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Object} attributeValues - values to filter deleted entities by
|
||||
* @param {Object} [trx]
|
||||
* @returns {Promise<integer>} Query builder. After promise is resolved, returns count of deleted rows
|
||||
*/
|
||||
deleteBy(attributeValues) {
|
||||
return this.model
|
||||
.query()
|
||||
.delete()
|
||||
.where(attributeValues);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string || number} id - value of id column of the entity
|
||||
* @returns {Promise<integer>} Query builder. After promise is resolved, returns count of deleted rows
|
||||
*/
|
||||
deleteById(id: number|string) {
|
||||
return this.deleteBy({
|
||||
[this.idColumn]: id
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} field -
|
||||
* @param {number|string} values -
|
||||
*/
|
||||
deleteWhereIn(field: string, values: string|number[]) {
|
||||
return this.model
|
||||
.query()
|
||||
.whereIn(field, values)
|
||||
.delete();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string|number[]} values
|
||||
*/
|
||||
deleteWhereIdIn(values: string|number[]) {
|
||||
return this.deleteWhereIn(this.idColumn, values);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param graph
|
||||
* @param options
|
||||
*/
|
||||
upsertGraph(graph, options) {
|
||||
// Keep the input grpah immutable
|
||||
const graphCloned = cloneDeep(graph);
|
||||
return this.model.upsertGraph(graphCloned)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {object} whereAttributes
|
||||
* @param {string} field
|
||||
* @param amount
|
||||
*/
|
||||
changeNumber(whereAttributes, field: string, amount: number) {
|
||||
const changeMethod = (amount > 0) ? 'increment' : 'decrement';
|
||||
|
||||
return this.model.query()
|
||||
.where(whereAttributes)
|
||||
[changeMethod](field, Math.abs(amount));
|
||||
}
|
||||
}
|
||||
12
server/src/repositories/ExpenseEntryRepository.ts
Normal file
12
server/src/repositories/ExpenseEntryRepository.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import TenantRepository from "./TenantRepository";
|
||||
import { ExpenseCategory } from 'models';
|
||||
|
||||
export default class ExpenseEntyRepository extends TenantRepository {
|
||||
/**
|
||||
* Constructor method.
|
||||
*/
|
||||
constructor(knex, cache) {
|
||||
super(knex, cache);
|
||||
this.model = ExpenseCategory;
|
||||
}
|
||||
}
|
||||
@@ -1,42 +1,13 @@
|
||||
import TenantRepository from "./TenantRepository";
|
||||
import { IExpense } from 'interfaces';
|
||||
import moment from "moment";
|
||||
|
||||
import { Expense } from 'models';
|
||||
export default class ExpenseRepository extends TenantRepository {
|
||||
/**
|
||||
* Retrieve the given expense by id.
|
||||
* @param {number} expenseId
|
||||
* @return {Promise<IExpense>}
|
||||
* Constructor method.
|
||||
*/
|
||||
getById(expenseId: number) {
|
||||
const { Expense } = this.models;
|
||||
return this.cache.get(`expense.id.${expenseId}`, () => {
|
||||
return Expense.query().findById(expenseId).withGraphFetched('categories');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a new expense object.
|
||||
* @param {IExpense} expense -
|
||||
*/
|
||||
async create(expenseInput: IExpense): Promise<void> {
|
||||
const { Expense } = this.models;
|
||||
const expense = await Expense.query().insertGraph({ ...expenseInput });
|
||||
this.flushCache();
|
||||
|
||||
return expense;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the given expense details.
|
||||
* @param {number} expenseId
|
||||
* @param {IExpense} expense
|
||||
*/
|
||||
async update(expenseId: number, expense: IExpense) {
|
||||
const { Expense } = this.models;
|
||||
|
||||
await Expense.query().findById(expenseId).patch({ ...expense });
|
||||
this.flushCache();
|
||||
constructor(knex, cache) {
|
||||
super(knex, cache);
|
||||
this.model = Expense;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,38 +15,10 @@ export default class ExpenseRepository extends TenantRepository {
|
||||
* @param {number} expenseId
|
||||
*/
|
||||
async publish(expenseId: number): Promise<void> {
|
||||
const { Expense } = this.models;
|
||||
|
||||
await Expense.query().findById(expenseId).patch({
|
||||
super.update({
|
||||
id: expenseId,
|
||||
publishedAt: moment().toMySqlDateTime(),
|
||||
});
|
||||
this.flushCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the given expense.
|
||||
* @param {number} expenseId
|
||||
*/
|
||||
async delete(expenseId: number): Promise<void> {
|
||||
const { Expense, ExpenseCategory } = this.models;
|
||||
|
||||
await ExpenseCategory.query().where('expense_id', expenseId).delete();
|
||||
await Expense.query().where('id', expenseId).delete();
|
||||
|
||||
this.flushCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes expenses in bulk.
|
||||
* @param {number[]} expensesIds
|
||||
*/
|
||||
async bulkDelete(expensesIds: number[]): Promise<void> {
|
||||
const { Expense, ExpenseCategory } = this.models;
|
||||
|
||||
await ExpenseCategory.query().whereIn('expense_id', expensesIds).delete();
|
||||
await Expense.query().whereIn('id', expensesIds).delete();
|
||||
|
||||
this.flushCache();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,18 +26,10 @@ export default class ExpenseRepository extends TenantRepository {
|
||||
* @param {number[]} expensesIds
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
async bulkPublish(expensesIds: number): Promise<void> {
|
||||
const { Expense } = this.models;
|
||||
await Expense.query().whereIn('id', expensesIds).patch({
|
||||
async whereIdInPublish(expensesIds: number): Promise<void> {
|
||||
await this.model.query().whereIn('id', expensesIds).patch({
|
||||
publishedAt: moment().toMySqlDateTime(),
|
||||
});
|
||||
this.flushCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes repository cache.
|
||||
*/
|
||||
flushCache() {
|
||||
this.cache.delStartWith(`expense`);
|
||||
}
|
||||
}
|
||||
13
server/src/repositories/ItemRepository.ts
Normal file
13
server/src/repositories/ItemRepository.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
import { Item } from "models";
|
||||
import TenantRepository from "./TenantRepository";
|
||||
|
||||
export default class ItemRepository extends TenantRepository {
|
||||
/**
|
||||
* Constructor method.
|
||||
*/
|
||||
constructor(knex, cache) {
|
||||
super(knex, cache);
|
||||
this.model = Item;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,12 @@
|
||||
import { IBalanceSheetQuery } from 'interfaces';
|
||||
import { ManualJournal } from 'models';
|
||||
import TenantRepository from 'repositories/TenantRepository';
|
||||
|
||||
|
||||
export default class JournalRepository extends TenantRepository {
|
||||
|
||||
balanceSheet(query: IBalanceSheetQuery) {
|
||||
|
||||
// Accounts dependency graph.
|
||||
const accountsGraph = Account.toDependencyGraph(balanceSheetAccounts);
|
||||
|
||||
// Load all entries that associated to the given accounts.
|
||||
const journalEntriesCollected = Account.collectJournalEntries(balanceSheetAccounts);
|
||||
|
||||
const journalEntries = new JournalPoster(accountsGraph);
|
||||
journalEntries.loadEntries(journalEntriesCollected);
|
||||
/**
|
||||
* Constructor method.
|
||||
*/
|
||||
constructor(knex, cache) {
|
||||
super(knex, cache);
|
||||
this.model = ManualJournal;
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
import { omit } from 'lodash';
|
||||
import BaseModelRepository from 'repositories/BaseModelRepository';
|
||||
import { PaymentReceiveEntry } from 'models';
|
||||
|
||||
export default class PaymentReceiveEntryRepository extends BaseModelRepository {
|
||||
/**
|
||||
* Insert payment receive entries in bulk.
|
||||
* @param {Array} entries
|
||||
* @param {Integr} paymentReceiveId
|
||||
* @return {Promise}
|
||||
*/
|
||||
static insertBulk(entries, paymentReceiveId) {
|
||||
const opers = [];
|
||||
entries.forEach((entry) => {
|
||||
const insertOper = PaymentReceiveEntry.tenant()
|
||||
.query()
|
||||
.insert({
|
||||
payment_receive_id: paymentReceiveId,
|
||||
...entry,
|
||||
});
|
||||
opers.push(insertOper);
|
||||
});
|
||||
return Promise.all(opers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update payment receive entries in bulk.
|
||||
* @param {Array} entries
|
||||
* @return {Promise}
|
||||
*/
|
||||
static updateBulk(entries) {
|
||||
const opers = [];
|
||||
entries.forEach((entry) => {
|
||||
const updateOper = PaymentReceiveEntry.tenant()
|
||||
.query()
|
||||
.patchAndFetchById(entry.id, {
|
||||
...omit(entry, ['id', 'index']),
|
||||
});
|
||||
opers.push(updateOper);
|
||||
});
|
||||
return Promise.all(opers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the given payment receive entries ids in bulk.
|
||||
* @param {Array} entriesIds
|
||||
* @return {Promise}
|
||||
*/
|
||||
static deleteBulk(entriesIds) {
|
||||
return PaymentReceiveEntry.tenant()
|
||||
.query()
|
||||
.whereIn('id', entriesIds)
|
||||
.delete();
|
||||
}
|
||||
}
|
||||
12
server/src/repositories/PaymentReceiveEntryRepository.ts
Normal file
12
server/src/repositories/PaymentReceiveEntryRepository.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { PaymentReceiveEntry } from 'models';
|
||||
import TenantRepository from 'repositories/TenantRepository';
|
||||
|
||||
export default class PaymentReceiveEntryRepository extends TenantRepository {
|
||||
/**
|
||||
* Constructor method.
|
||||
*/
|
||||
constructor(knex, cache) {
|
||||
super(knex, cache);
|
||||
this.model = PaymentReceiveEntry;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import { omit } from 'lodash';
|
||||
import { PaymentReceiveEntry } from 'models';
|
||||
import BaseModelRepository from 'repositories/BaseModelRepository';
|
||||
|
||||
export default class PaymentReceiveRepository extends BaseModelRepository {
|
||||
|
||||
}
|
||||
12
server/src/repositories/PaymentReceiveRepository.ts
Normal file
12
server/src/repositories/PaymentReceiveRepository.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { PaymentReceive } from 'models';
|
||||
import TenantRepository from 'repositories/TenantRepository';
|
||||
|
||||
export default class PaymentReceiveRepository extends TenantRepository {
|
||||
/**
|
||||
* Constructor method.
|
||||
*/
|
||||
constructor(knex, cache) {
|
||||
super(knex, cache);
|
||||
this.model = PaymentReceive;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
|
||||
|
||||
export default class SaleInvoiceRepository {
|
||||
|
||||
|
||||
|
||||
}
|
||||
12
server/src/repositories/SaleInvoiceRepository.ts
Normal file
12
server/src/repositories/SaleInvoiceRepository.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { SaleInvoice } from 'models';
|
||||
import TenantRepository from 'repositories/TenantRepository';
|
||||
|
||||
export default class SaleInvoiceRepository extends TenantRepository {
|
||||
/**
|
||||
* Constructor method.
|
||||
*/
|
||||
constructor(knex, cache) {
|
||||
super(knex, cache);
|
||||
this.model = SaleInvoice;
|
||||
}
|
||||
}
|
||||
12
server/src/repositories/SettingRepository.ts
Normal file
12
server/src/repositories/SettingRepository.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import TenantRepository from 'repositories/TenantRepository';
|
||||
import Setting from 'models/Setting';
|
||||
|
||||
export default class SettingRepository extends TenantRepository {
|
||||
/**
|
||||
* Constructor method.
|
||||
*/
|
||||
constructor(knex, cache) {
|
||||
super(knex, cache);
|
||||
this.model = Setting;
|
||||
}
|
||||
}
|
||||
@@ -4,42 +4,13 @@ import CachableRepository from './CachableRepository';
|
||||
|
||||
export default class TenantRepository extends CachableRepository {
|
||||
repositoryName: string;
|
||||
tenantId: number;
|
||||
tenancy: TenancyService;
|
||||
modelsInstance: any;
|
||||
repositoriesInstance: any;
|
||||
cacheInstance: any;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor method.
|
||||
* @param {number} tenantId
|
||||
*/
|
||||
constructor(tenantId: number) {
|
||||
super();
|
||||
|
||||
this.tenantId = tenantId;
|
||||
this.tenancy = Container.get(TenancyService);
|
||||
constructor(knex, cache) {
|
||||
super(knex, cache);
|
||||
this.repositoryName = this.constructor.name;
|
||||
}
|
||||
|
||||
get models() {
|
||||
if (!this.modelsInstance) {
|
||||
this.modelsInstance = this.tenancy.models(this.tenantId);
|
||||
}
|
||||
return this.modelsInstance;
|
||||
}
|
||||
|
||||
get repositories() {
|
||||
if (!this.repositoriesInstance) {
|
||||
this.repositoriesInstance = this.tenancy.repositories(this.tenantId);
|
||||
}
|
||||
return this.repositoriesInstance;
|
||||
}
|
||||
|
||||
get cache() {
|
||||
if (!this.cacheInstance) {
|
||||
this.cacheInstance = this.tenancy.cache(this.tenantId);
|
||||
}
|
||||
return this.cacheInstance;
|
||||
}
|
||||
}
|
||||
@@ -1,58 +1,17 @@
|
||||
import { IVendor } from "interfaces";
|
||||
import { Vendor } from "models";
|
||||
import TenantRepository from "./TenantRepository";
|
||||
|
||||
|
||||
export default class VendorRepository extends TenantRepository {
|
||||
|
||||
/**
|
||||
* Retrieve vendor details of the given id.
|
||||
* @param {number} vendorId - Vendor id.
|
||||
* Constructor method.
|
||||
*/
|
||||
findById(vendorId: number) {
|
||||
const { Contact } = this.models;
|
||||
return Contact.query().findById(vendorId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the bill that associated to the given vendor id.
|
||||
* @param {number} vendorId - Vendor id.
|
||||
*/
|
||||
getBills(vendorId: number) {
|
||||
const { Bill } = this.models;
|
||||
|
||||
return this.cache.get(`vendors.bills.${vendorId}`, () => {
|
||||
return Bill.query().where('vendor_id', vendorId);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all the given vendors.
|
||||
* @param {numner[]} vendorsIds
|
||||
* @return {IVendor}
|
||||
*/
|
||||
vendors(vendorsIds: number[]): IVendor[] {
|
||||
const { Contact } = this.models;
|
||||
return Contact.query().modifier('vendor').whereIn('id', vendorsIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve vendors with associated bills.
|
||||
* @param {number[]} vendorIds
|
||||
*/
|
||||
vendorsWithBills(vendorIds: number[]) {
|
||||
const { Contact } = this.models;
|
||||
return Contact.query().modify('vendor')
|
||||
.whereIn('id', vendorIds)
|
||||
.withGraphFetched('bills');
|
||||
constructor(knex, cache) {
|
||||
super(knex, cache);
|
||||
this.model = Vendor;
|
||||
}
|
||||
|
||||
changeBalance(vendorId: number, amount: number) {
|
||||
const { Contact } = this.models;
|
||||
const changeMethod = (amount > 0) ? 'increment' : 'decrement';
|
||||
|
||||
return Contact.query()
|
||||
.where('id', vendorId)
|
||||
[changeMethod]('balance', Math.abs(amount));
|
||||
return super.changeNumber({ id: vendorId }, 'balance', amount);
|
||||
}
|
||||
|
||||
async changeDiffBalance(
|
||||
|
||||
@@ -1,60 +1,19 @@
|
||||
import { IView } from 'interfaces';
|
||||
import { View } from 'models';
|
||||
import TenantRepository from 'repositories/TenantRepository';
|
||||
|
||||
export default class ViewRepository extends TenantRepository {
|
||||
|
||||
/**
|
||||
* Retrieve view model by the given id.
|
||||
* @param {number} id -
|
||||
* Constructor method.
|
||||
*/
|
||||
getById(id: number) {
|
||||
const { View } = this.models;
|
||||
return this.cache.get(`customView.id.${id}`, () => {
|
||||
return View.query().findById(id)
|
||||
.withGraphFetched('columns')
|
||||
.withGraphFetched('roles');
|
||||
});
|
||||
constructor(knex, cache) {
|
||||
super(knex, cache);
|
||||
this.model = View;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all views of the given resource id.
|
||||
*/
|
||||
allByResource(resourceModel: string) {
|
||||
const { View } = this.models;
|
||||
return this.cache.get(`customView.resourceModel.${resourceModel}`, () => {
|
||||
return View.query().where('resource_model', resourceModel)
|
||||
.withGraphFetched('columns')
|
||||
.withGraphFetched('roles');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a new view to the storage.
|
||||
* @param {IView} view
|
||||
*/
|
||||
async insert(view: IView): Promise<IView> {
|
||||
const { View } = this.models;
|
||||
const insertedView = await View.query().insertGraph({ ...view });
|
||||
this.flushCache();
|
||||
|
||||
return insertedView;
|
||||
}
|
||||
|
||||
async update(viewId: number, view: IView): Promise<IView> {
|
||||
const { View } = this.models;
|
||||
const updatedView = await View.query().upsertGraph({
|
||||
id: viewId,
|
||||
...view
|
||||
});
|
||||
this.flushCache();
|
||||
|
||||
return updatedView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes repository cache.
|
||||
*/
|
||||
flushCache() {
|
||||
this.cache.delStartWith('customView');
|
||||
allByResource(resourceModel: string, withRelations?) {
|
||||
return super.find({ resource_mode: resourceModel }, withRelations);
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,4 @@ import TenantRepository from 'repositories/TenantRepository';
|
||||
|
||||
export default class ViewRoleRepository extends TenantRepository {
|
||||
|
||||
allByView(viewId: number) {
|
||||
const { ViewRole } = this.models;
|
||||
return this.cache.get(`viewRole.view.${viewId}`, async () => {
|
||||
return ViewRole.query().where('view_id', viewId);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
import ResourceRepository from './ResourceRepository';
|
||||
|
||||
export {
|
||||
ResourceRepository,
|
||||
};
|
||||
Reference in New Issue
Block a user