add server to monorepo.

This commit is contained in:
a.bouhuolia
2023-02-03 11:57:50 +02:00
parent 28e309981b
commit 80b97b5fdc
1303 changed files with 137049 additions and 0 deletions

View File

@@ -0,0 +1,158 @@
import { Account } from 'models';
import TenantRepository from '@/repositories/TenantRepository';
import { IAccount } from '@/interfaces';
import { Knex } from 'knex';
export default class AccountRepository extends TenantRepository {
/**
* Gets the repository's model.
*/
get model() {
return Account.bindKnex(this.knex);
}
/**
* Retrieve accounts dependency graph.
* @returns {}
*/
async getDependencyGraph(withRelation, trx) {
const accounts = await this.all(withRelation, trx);
return this.model.toDependencyGraph(accounts);
}
/**
* Retrieve.
* @param {string} slug
* @return {Promise<IAccount>}
*/
findBySlug(slug: string) {
return this.findOne({ slug });
}
/**
* Changes account balance.
* @param {number} accountId
* @param {number} amount
* @return {Promise<void>}
*/
async balanceChange(accountId: number, amount: number): Promise<void> {
const method: string = amount < 0 ? 'decrement' : 'increment';
await this.model.query().where('id', accountId)[method]('amount', amount);
this.flushCache();
}
/**
* Activate user by the given id.
* @param {number} userId - User id.
* @return {Promise<void>}
*/
activateById(userId: number): Promise<IAccount> {
return super.update({ active: 1 }, { id: userId });
}
/**
* Inactivate user by the given id.
* @param {number} userId - User id.
* @return {Promise<void>}
*/
inactivateById(userId: number): Promise<void> {
return super.update({ active: 0 }, { id: userId });
}
/**
* Activate user by the given id.
* @param {number} userId - User id.
* @return {Promise<void>}
*/
async activateByIds(userIds: number[], trx): Promise<IAccount> {
const results = await this.model
.query(trx)
.whereIn('id', userIds)
.patch({ active: true });
this.flushCache();
return results;
}
/**
* Inactivate user by the given id.
* @param {number} userId - User id.
* @return {Promise<void>}
*/
async inactivateByIds(userIds: number[], trx): Promise<IAccount> {
const results = await this.model
.query(trx)
.whereIn('id', userIds)
.patch({ active: false });
this.flushCache();
return results;
}
/**
*
* @param {string} currencyCode
* @param extraAttrs
* @param trx
* @returns
*/
findOrCreateAccountReceivable = async (
currencyCode: string = '',
extraAttrs = {},
trx?: Knex.Transaction
) => {
let result = await this.model
.query(trx)
.onBuild((query) => {
if (currencyCode) {
query.where('currencyCode', currencyCode);
}
query.where('accountType', 'accounts-receivable');
})
.first();
if (!result) {
result = await this.model.query(trx).insertAndFetch({
name: this.i18n.__('account.accounts_receivable.currency', {
currency: currencyCode
}),
accountType: 'accounts-receivable',
currencyCode,
active: 1,
...extraAttrs,
});
}
return result;
};
findOrCreateAccountsPayable = async (
currencyCode: string = '',
extraAttrs = {},
trx?: Knex.Transaction
) => {
let result = await this.model
.query(trx)
.onBuild((query) => {
if (currencyCode) {
query.where('currencyCode', currencyCode);
}
query.where('accountType', 'accounts-payable');
})
.first();
if (!result) {
result = await this.model.query(trx).insertAndFetch({
name: this.i18n.__('account.accounts_payable.currency', {
currency: currencyCode,
}),
accountType: 'accounts-payable',
currencyCode,
active: 1,
...extraAttrs,
});
}
return result;
};
}

View File

@@ -0,0 +1,99 @@
import { isEmpty, castArray } from 'lodash';
import { AccountTransaction } from 'models';
import TenantRepository from '@/repositories/TenantRepository';
interface IJournalTransactionsFilter {
fromDate: string | Date;
toDate: string | Date;
accountsIds: number[];
sumationCreditDebit: boolean;
fromAmount: number;
toAmount: number;
contactsIds?: number[];
contactType?: string;
referenceType?: string[];
referenceId?: number[];
index: number | number[];
indexGroup: number | number[];
branchesIds: number | number[];
}
export default class AccountTransactionsRepository extends TenantRepository {
/**
* Gets the repository's model.
*/
get model() {
return AccountTransaction.bindKnex(this.knex);
}
journal(filter: IJournalTransactionsFilter) {
return this.model
.query()
.modify('filterAccounts', filter.accountsIds)
.modify('filterDateRange', filter.fromDate, filter.toDate)
.withGraphFetched('account')
.onBuild((query) => {
if (filter.sumationCreditDebit) {
query.modify('sumationCreditDebit');
}
if (filter.fromAmount || filter.toAmount) {
query.modify('filterAmountRange', filter.fromAmount, filter.toAmount);
}
if (filter.contactsIds) {
query.modify('filterContactIds', filter.contactsIds);
}
if (filter.contactType) {
query.where('contact_type', filter.contactType);
}
if (filter.referenceType && filter.referenceType.length > 0) {
query.whereIn('reference_type', filter.referenceType);
}
if (filter.referenceId && filter.referenceId.length > 0) {
query.whereIn('reference_id', filter.referenceId);
}
if (filter.index) {
if (Array.isArray(filter.index)) {
query.whereIn('index', filter.index);
} else {
query.where('index', filter.index);
}
}
if (filter.indexGroup) {
if (Array.isArray(filter.indexGroup)) {
query.whereIn('index_group', filter.indexGroup);
} else {
query.where('index_group', filter.indexGroup);
}
}
if (!isEmpty(filter.branchesIds)) {
query.modify('filterByBranches', filter.branchesIds);
}
});
}
openingBalance(fromDate) {
return AccountTransaction.query().modify('openingBalance', fromDate);
}
closingOpening(toDate) {
return AccountTransaction.query().modify('closingBalance', toDate);
}
/**
* Reverts the jouranl entries.
* @param {number|number[]} referenceId - Reference id.
* @param {string} referenceType - Reference type.
*/
public getTransactionsByReference = async (
referenceId: number | number[],
referenceType: string | string[]
) => {
const transactions = await this.model
.query()
.whereIn('reference_type', castArray(referenceType))
.whereIn('reference_id', castArray(referenceId))
.withGraphFetched('account');
return transactions;
};
}

View File

@@ -0,0 +1,5 @@
export default class BaseModelRepository {
}

View File

@@ -0,0 +1,30 @@
import moment from 'moment';
import { Bill } from 'models';
import TenantRepository from '@/repositories/TenantRepository';
export default class BillRepository extends TenantRepository {
/**
* Gets the repository's model.
*/
get model() {
return Bill.bindKnex(this.knex);
}
dueBills(asDate = moment().format('YYYY-MM-DD'), withRelations) {
return this.model
.query()
.modify('dueBills')
.modify('notOverdue')
.modify('fromDate', asDate)
.withGraphFetched(withRelations);
}
overdueBills(asDate = moment().format('YYYY-MM-DD'), withRelations) {
return this.model
.query()
.modify('dueBills')
.modify('overdue', asDate)
.modify('fromDate', asDate)
.withGraphFetched(withRelations);
}
}

View File

@@ -0,0 +1,261 @@
import hashObject from 'object-hash';
import EntityRepository from './EntityRepository';
export default class CachableRepository extends EntityRepository {
repositoryName: string;
cache: any;
i18n: any;
/**
* Constructor method.
* @param {Knex} knex
* @param {Cache} cache
*/
constructor(knex, cache, i18n) {
super(knex);
this.cache = cache;
this.i18n = i18n;
this.repositoryName = this.constructor.name;
}
getByCache(key, callback) {
return callback();
}
/**
* Retrieve the cache key of the method name and arguments.
* @param {string} method
* @param {...any} args
* @return {string}
*/
getCacheKey(method, ...args) {
const hashArgs = hashObject({ ...args });
const repositoryName = this.repositoryName;
return `${repositoryName}-${method}-${hashArgs}`;
}
/**
* Retrieve all entries with specified relations.
* @param withRelations
*/
all(withRelations?, trx?) {
const cacheKey = this.getCacheKey('all', withRelations);
return this.getByCache(cacheKey, () => {
return super.all(withRelations, trx);
});
}
/**
* 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.getByCache(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.getByCache(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.getByCache(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.getByCache(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.getByCache(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, trx?) {
const result = await super.create(entity, trx);
// 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?, trx?) {
const result = await super.update(entity, whereAttributes, trx);
// 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, trx?) {
const result = await super.deleteBy(attributeValues, trx);
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, trx?) {
const result = super.deleteById(id, trx);
// Flushes the repository cache after insert operation.
this.flushCache();
return result;
}
/**
*
* @param {string|number[]} values -
*/
async deleteWhereIn(field: string, values: string | number[]) {
const result = await super.deleteWhereIn(field, values);
// Flushes the repository cache after delete operation.
this.flushCache();
return result;
}
/**
*
* @param {string|number[]} values
*/
async deleteWhereIdIn(values: string | number[], trx?) {
const result = await super.deleteWhereIdIn(values, trx);
// 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, trx?) {
const result = await super.changeNumber(
whereAttributes,
field,
amount,
trx
);
// Flushes the repository cache after update operation.
this.flushCache();
return result;
}
/**
* Flush repository cache.
*/
flushCache(): void {
this.cache.delStartWith(this.repositoryName);
}
}

View File

@@ -0,0 +1,12 @@
import TenantRepository from '@/repositories/TenantRepository';
import { Contact } from 'models'
export default class ContactRepository extends TenantRepository {
/**
* Gets the repository's model.
*/
get model() {
return Contact.bindKnex(this.knex);
}
}

View File

@@ -0,0 +1,46 @@
import TenantRepository from "./TenantRepository";
import { Customer } from 'models';
export default class CustomerRepository extends TenantRepository {
/**
* Contact repository.
*/
constructor(knex, cache, i18n) {
super(knex, cache, i18n);
this.repositoryName = 'CustomerRepository';
}
/**
* Gets the repository's model.
*/
get model() {
return Customer.bindKnex(this.knex);
}
changeBalance(vendorId: number, amount: number) {
return super.changeNumber({ id: vendorId }, 'balance', amount);
}
async changeDiffBalance(
vendorId: number,
amount: number,
oldAmount: number,
oldVendorId?: number,
) {
const diffAmount = amount - oldAmount;
const asyncOpers = [];
const _oldVendorId = oldVendorId || vendorId;
if (vendorId != _oldVendorId) {
const oldCustomerOper = this.changeBalance(_oldVendorId, (oldAmount * -1));
const customerOper = this.changeBalance(vendorId, amount);
asyncOpers.push(customerOper);
asyncOpers.push(oldCustomerOper);
} else {
const balanceChangeOper = this.changeBalance(vendorId, diffAmount);
asyncOpers.push(balanceChangeOper);
}
await Promise.all(asyncOpers);
}
}

View File

@@ -0,0 +1,241 @@
import { cloneDeep, forOwn, isString } from 'lodash';
import ModelEntityNotFound from 'exceptions/ModelEntityNotFound';
function applyGraphFetched(withRelations, builder) {
const relations = Array.isArray(withRelations)
? withRelations
: typeof withRelations === 'string'
? withRelations.split(',').map((relation) => relation.trim())
: [];
relations.forEach((relation) => {
builder.withGraphFetched(relation);
});
}
export default class EntityRepository {
idColumn: string;
knex: any;
/**
* Constructor method.
* @param {Knex} knex
*/
constructor(knex) {
this.knex = knex;
this.idColumn = 'id';
}
/**
* Retrieve the repository model binded it to knex instance.
*/
get model() {
throw new Error("The repository's model is not defined.");
}
/**
* Retrieve all entries with specified relations.
*
* @param withRelations
*/
all(withRelations?, trx?) {
const builder = this.model.query(trx);
applyGraphFetched(withRelations, builder);
return builder;
}
/**
* 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 builder = this.model.query().where(attributeValues);
applyGraphFetched(withRelations, builder);
return builder;
}
/**
* 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?) {
const builder = this.model.query().whereNot(attributeValues);
applyGraphFetched(withRelations, builder);
return builder;
}
/**
* 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 commonBuilder = (builder) => {
applyGraphFetched(withRelations, builder);
};
if (isString(searchParam)) {
return this.model
.query()
.whereIn(searchParam, attributeValues)
.onBuild(commonBuilder);
} else {
const builder = this.model.query(this.knex).onBuild(commonBuilder);
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, trx?) {
// Keep the input parameter immutable
const instanceDTO = cloneDeep(entity);
return this.model.query(trx).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?, trx?) {
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(trx)
.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, trx?) {
return this.model.query(trx).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, trx?) {
return this.deleteBy(
{
[this.idColumn]: id,
},
trx
);
}
/**
* Deletes the given entries in the array on the specific field.
* @param {string} field -
* @param {number|string} values -
*/
deleteWhereIn(field: string, values: string | number[], trx) {
return this.model.query(trx).whereIn(field, values).delete();
}
/**
*
* @param {string|number[]} values
*/
deleteWhereIdIn(values: string | number[], trx?) {
return this.deleteWhereIn(this.idColumn, values, trx);
}
/**
* Arbitrary relation graphs can be upserted (insert + update + delete)
* using the upsertGraph method.
* @param graph
* @param options
*/
upsertGraph(graph, options) {
// Keep the input grpah immutable
const graphCloned = cloneDeep(graph);
return this.model.query().upsertGraph(graphCloned, options);
}
/**
*
* @param {object} whereAttributes
* @param {string} field
* @param amount
*/
changeNumber(whereAttributes, field: string, amount: number, trx) {
const changeMethod = amount > 0 ? 'increment' : 'decrement';
return this.model
.query(trx)
.where(whereAttributes)
[changeMethod](field, Math.abs(amount));
}
}

View File

@@ -0,0 +1,11 @@
import TenantRepository from "./TenantRepository";
import { ExpenseCategory } from 'models';
export default class ExpenseEntryRepository extends TenantRepository {
/**
* Gets the repository's model.
*/
get model() {
return ExpenseCategory.bindKnex(this.knex);
}
}

View File

@@ -0,0 +1,35 @@
import TenantRepository from "./TenantRepository";
import moment from "moment";
import { Expense } from 'models';
export default class ExpenseRepository extends TenantRepository {
/**
* Gets the repository's model.
*/
get model() {
return Expense.bindKnex(this.knex);
}
/**
* Publish the given expense.
* @param {number} expenseId
*/
publish(expenseId: number): Promise<void> {
return super.update({
id: expenseId,
publishedAt: moment().toMySqlDateTime(),
});
}
/**
* Publishes the given expenses in bulk.
* @param {number[]} expensesIds
* @return {Promise<void>}
*/
async whereIdInPublish(expensesIds: number): Promise<void> {
await this.model.query().whereIn('id', expensesIds).patch({
publishedAt: moment().toMySqlDateTime(),
});
this.flushCache();
}
}

View File

@@ -0,0 +1,11 @@
import TenantRepository from '@/repositories/TenantRepository';
import { InventoryTransaction } from 'models';
export default class InventoryTransactionRepository extends TenantRepository {
/**
* Gets the repository's model.
*/
get model() {
return InventoryTransaction.bindKnex(this.knex);
}
}

View File

@@ -0,0 +1,12 @@
import { Item } from "models";
import TenantRepository from "./TenantRepository";
export default class ItemRepository extends TenantRepository {
/**
* Gets the repository's model.
*/
get model() {
return Item.bindKnex(this.knex);
}
}

View File

@@ -0,0 +1,11 @@
import { ManualJournal } from 'models';
import TenantRepository from '@/repositories/TenantRepository';
export default class JournalRepository extends TenantRepository {
/**
* Gets the repository's model.
*/
get model() {
return ManualJournal.bindKnex(this.knex);
}
}

View File

@@ -0,0 +1,11 @@
import { PaymentReceiveEntry } from 'models';
import TenantRepository from '@/repositories/TenantRepository';
export default class PaymentReceiveEntryRepository extends TenantRepository {
/**
* Gets the repository's model.
*/
get model() {
return PaymentReceiveEntry.bindKnex(this.knex);
}
}

View File

@@ -0,0 +1,11 @@
import { PaymentReceive } from 'models';
import TenantRepository from '@/repositories/TenantRepository';
export default class PaymentReceiveRepository extends TenantRepository {
/**
* Gets the repository's model.
*/
get model() {
return PaymentReceive.bindKnex(this.knex);
}
}

View File

@@ -0,0 +1,30 @@
import moment from 'moment';
import { SaleInvoice } from 'models';
import TenantRepository from '@/repositories/TenantRepository';
export default class SaleInvoiceRepository extends TenantRepository {
/**
* Gets the repository's model.
*/
get model() {
return SaleInvoice.bindKnex(this.knex);
}
dueInvoices(asDate = moment().format('YYYY-MM-DD'), withRelations) {
return this.model
.query()
.modify('dueInvoices')
.modify('notOverdue', asDate)
.modify('fromDate', asDate)
.withGraphFetched(withRelations);
}
overdueInvoices(asDate = moment().format('YYYY-MM-DD'), withRelations) {
return this.model
.query()
.modify('dueInvoices')
.modify('overdue', asDate)
.modify('fromDate', asDate)
.withGraphFetched(withRelations);
}
}

View File

@@ -0,0 +1,11 @@
import TenantRepository from '@/repositories/TenantRepository';
import Setting from 'models/Setting';
export default class SettingRepository extends TenantRepository {
/**
* Gets the repository's model.
*/
get model() {
return Setting.bindKnex(this.knex);
}
}

View File

@@ -0,0 +1,15 @@
import { Container } from 'typedi';
import TenancyService from '@/services/Tenancy/TenancyService';
import CachableRepository from './CachableRepository';
export default class TenantRepository extends CachableRepository {
repositoryName: string;
/**
* Constructor method.
* @param {number} tenantId
*/
constructor(knex, cache, i18n) {
super(knex, cache, i18n);
}
}

View File

@@ -0,0 +1,50 @@
import { Vendor } from "models";
import TenantRepository from "./TenantRepository";
export default class VendorRepository extends TenantRepository {
/**
* Contact repository.
*/
constructor(knex, cache, i18n) {
super(knex, cache, i18n);
this.repositoryName = 'VendorRepository';
}
/**
* Gets the repository's model.
*/
get model() {
return Vendor.bindKnex(this.knex);
}
unpaid() {
}
changeBalance(vendorId: number, amount: number) {
return super.changeNumber({ id: vendorId }, 'balance', amount);
}
async changeDiffBalance(
vendorId: number,
amount: number,
oldAmount: number,
oldVendorId?: number,
) {
const diffAmount = amount - oldAmount;
const asyncOpers = [];
const _oldVendorId = oldVendorId || vendorId;
if (vendorId != _oldVendorId) {
const oldCustomerOper = this.changeBalance(_oldVendorId, (oldAmount * -1));
const customerOper = this.changeBalance(vendorId, amount);
asyncOpers.push(customerOper);
asyncOpers.push(oldCustomerOper);
} else {
const balanceChangeOper = this.changeBalance(vendorId, diffAmount);
asyncOpers.push(balanceChangeOper);
}
await Promise.all(asyncOpers);
}
}

View File

@@ -0,0 +1,18 @@
import { View } from 'models';
import TenantRepository from '@/repositories/TenantRepository';
export default class ViewRepository extends TenantRepository {
/**
* Gets the repository's model.
*/
get model() {
return View.bindKnex(this.knex);
}
/**
* Retrieve all views of the given resource id.
*/
allByResource(resourceModel: string, withRelations?) {
return super.find({ resource_model: resourceModel }, withRelations);
}
}

View File

@@ -0,0 +1,6 @@
import { omit } from 'lodash';
import TenantRepository from '@/repositories/TenantRepository';
export default class ViewRoleRepository extends TenantRepository {
}