mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-16 04:40:32 +00:00
WIP: Allocate landed cost.
This commit is contained in:
@@ -103,6 +103,7 @@ export default class Bill extends TenantModel {
|
||||
'remainingDays',
|
||||
'overdueDays',
|
||||
'isOverdue',
|
||||
'unallocatedCostAmount'
|
||||
];
|
||||
}
|
||||
|
||||
@@ -178,6 +179,14 @@ export default class Bill extends TenantModel {
|
||||
return this.overdueDays > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the unallocated cost amount.
|
||||
* @return {number}
|
||||
*/
|
||||
get unallocatedCostAmount() {
|
||||
return Math.max(this.landedCostAmount - this.allocatedCostAmount, 0);
|
||||
}
|
||||
|
||||
getOverdueDays(asDate = moment().format('YYYY-MM-DD')) {
|
||||
// Can't continue in case due date not defined.
|
||||
if (!this.dueDate) {
|
||||
@@ -195,6 +204,7 @@ export default class Bill extends TenantModel {
|
||||
static get relationMappings() {
|
||||
const Contact = require('models/Contact');
|
||||
const ItemEntry = require('models/ItemEntry');
|
||||
const BillLandedCost = require('models/BillLandedCost');
|
||||
|
||||
return {
|
||||
vendor: {
|
||||
@@ -220,6 +230,15 @@ export default class Bill extends TenantModel {
|
||||
builder.where('reference_type', 'Bill');
|
||||
},
|
||||
},
|
||||
|
||||
locatedLandedCosts: {
|
||||
relation: Model.HasManyRelation,
|
||||
modelClass: BillLandedCost.default,
|
||||
join: {
|
||||
from: 'bills.id',
|
||||
to: 'bill_located_costs.billId',
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
36
server/src/models/BillLandedCost.js
Normal file
36
server/src/models/BillLandedCost.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import { Model } from 'objection';
|
||||
import TenantModel from 'models/TenantModel';
|
||||
|
||||
export default class BillLandedCost extends TenantModel {
|
||||
/**
|
||||
* Table name
|
||||
*/
|
||||
static get tableName() {
|
||||
return 'bill_located_costs';
|
||||
}
|
||||
|
||||
/**
|
||||
* Model timestamps.
|
||||
*/
|
||||
get timestamps() {
|
||||
return ['createdAt', 'updatedAt'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Relationship mapping.
|
||||
*/
|
||||
static get relationMappings() {
|
||||
const BillLandedCostEntry = require('models/BillLandedCostEntry');
|
||||
|
||||
return {
|
||||
allocateEntries: {
|
||||
relation: Model.HasManyRelation,
|
||||
modelClass: BillLandedCostEntry.default,
|
||||
join: {
|
||||
from: 'bill_located_costs.id',
|
||||
to: 'bill_located_cost_entries.billLocatedCostId',
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
10
server/src/models/BillLandedCostEntry.js
Normal file
10
server/src/models/BillLandedCostEntry.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import TenantModel from 'models/TenantModel';
|
||||
|
||||
export default class BillLandedCostEntry extends TenantModel {
|
||||
/**
|
||||
* Table name
|
||||
*/
|
||||
static get tableName() {
|
||||
return 'bill_located_cost_entries';
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,27 @@
|
||||
import { Model } from "objection";
|
||||
import TenantModel from "models/TenantModel";
|
||||
import { viewRolesBuilder } from "lib/ViewRolesBuilder";
|
||||
import { Model } from 'objection';
|
||||
import TenantModel from 'models/TenantModel';
|
||||
import { viewRolesBuilder } from 'lib/ViewRolesBuilder';
|
||||
|
||||
export default class Expense extends TenantModel {
|
||||
/**
|
||||
* Table name
|
||||
*/
|
||||
static get tableName() {
|
||||
return "expenses_transactions";
|
||||
return 'expenses_transactions';
|
||||
}
|
||||
|
||||
/**
|
||||
* Account transaction reference type.
|
||||
*/
|
||||
static get referenceType() {
|
||||
return "Expense";
|
||||
return 'Expense';
|
||||
}
|
||||
|
||||
/**
|
||||
* Model timestamps.
|
||||
*/
|
||||
get timestamps() {
|
||||
return ["createdAt", "updatedAt"];
|
||||
return ['createdAt', 'updatedAt'];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -37,14 +37,19 @@ export default class Expense extends TenantModel {
|
||||
static get media() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static get virtualAttributes() {
|
||||
return ["isPublished"];
|
||||
return ['isPublished', 'unallocatedLandedCost'];
|
||||
}
|
||||
|
||||
isPublished() {
|
||||
return Boolean(this.publishedAt);
|
||||
}
|
||||
|
||||
unallocatedLandedCost() {
|
||||
return Math.max(this.amount - this.allocatedCostAmount, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Model modifiers.
|
||||
*/
|
||||
@@ -52,28 +57,28 @@ export default class Expense extends TenantModel {
|
||||
return {
|
||||
filterByDateRange(query, startDate, endDate) {
|
||||
if (startDate) {
|
||||
query.where("date", ">=", startDate);
|
||||
query.where('date', '>=', startDate);
|
||||
}
|
||||
if (endDate) {
|
||||
query.where("date", "<=", endDate);
|
||||
query.where('date', '<=', endDate);
|
||||
}
|
||||
},
|
||||
filterByAmountRange(query, from, to) {
|
||||
if (from) {
|
||||
query.where("amount", ">=", from);
|
||||
query.where('amount', '>=', from);
|
||||
}
|
||||
if (to) {
|
||||
query.where("amount", "<=", to);
|
||||
query.where('amount', '<=', to);
|
||||
}
|
||||
},
|
||||
filterByExpenseAccount(query, accountId) {
|
||||
if (accountId) {
|
||||
query.where("expense_account_id", accountId);
|
||||
query.where('expense_account_id', accountId);
|
||||
}
|
||||
},
|
||||
filterByPaymentAccount(query, accountId) {
|
||||
if (accountId) {
|
||||
query.where("payment_account_id", accountId);
|
||||
query.where('payment_account_id', accountId);
|
||||
}
|
||||
},
|
||||
viewRolesBuilder(query, conditionals, expression) {
|
||||
@@ -94,40 +99,40 @@ export default class Expense extends TenantModel {
|
||||
* Relationship mapping.
|
||||
*/
|
||||
static get relationMappings() {
|
||||
const Account = require("models/Account");
|
||||
const ExpenseCategory = require("models/ExpenseCategory");
|
||||
const Media = require("models/Media");
|
||||
const Account = require('models/Account');
|
||||
const ExpenseCategory = require('models/ExpenseCategory');
|
||||
const Media = require('models/Media');
|
||||
|
||||
return {
|
||||
paymentAccount: {
|
||||
relation: Model.BelongsToOneRelation,
|
||||
modelClass: Account.default,
|
||||
join: {
|
||||
from: "expenses_transactions.paymentAccountId",
|
||||
to: "accounts.id",
|
||||
from: 'expenses_transactions.paymentAccountId',
|
||||
to: 'accounts.id',
|
||||
},
|
||||
},
|
||||
categories: {
|
||||
relation: Model.HasManyRelation,
|
||||
modelClass: ExpenseCategory.default,
|
||||
join: {
|
||||
from: "expenses_transactions.id",
|
||||
to: "expense_transaction_categories.expenseId",
|
||||
from: 'expenses_transactions.id',
|
||||
to: 'expense_transaction_categories.expenseId',
|
||||
},
|
||||
},
|
||||
media: {
|
||||
relation: Model.ManyToManyRelation,
|
||||
modelClass: Media.default,
|
||||
join: {
|
||||
from: "expenses_transactions.id",
|
||||
from: 'expenses_transactions.id',
|
||||
through: {
|
||||
from: "media_links.model_id",
|
||||
to: "media_links.media_id",
|
||||
from: 'media_links.model_id',
|
||||
to: 'media_links.media_id',
|
||||
},
|
||||
to: "media.id",
|
||||
to: 'media.id',
|
||||
},
|
||||
filter(query) {
|
||||
query.where("model_name", "Expense");
|
||||
query.where('model_name', 'Expense');
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -139,39 +144,39 @@ export default class Expense extends TenantModel {
|
||||
static get fields() {
|
||||
return {
|
||||
payment_date: {
|
||||
label: "Payment date",
|
||||
column: "payment_date",
|
||||
columnType: "date",
|
||||
label: 'Payment date',
|
||||
column: 'payment_date',
|
||||
columnType: 'date',
|
||||
},
|
||||
payment_account: {
|
||||
label: "Payment account",
|
||||
column: "payment_account_id",
|
||||
relation: "accounts.id",
|
||||
optionsResource: "account",
|
||||
label: 'Payment account',
|
||||
column: 'payment_account_id',
|
||||
relation: 'accounts.id',
|
||||
optionsResource: 'account',
|
||||
},
|
||||
amount: {
|
||||
label: "Amount",
|
||||
column: "total_amount",
|
||||
columnType: "number",
|
||||
label: 'Amount',
|
||||
column: 'total_amount',
|
||||
columnType: 'number',
|
||||
},
|
||||
currency_code: {
|
||||
label: "Currency",
|
||||
column: "currency_code",
|
||||
optionsResource: "currency",
|
||||
label: 'Currency',
|
||||
column: 'currency_code',
|
||||
optionsResource: 'currency',
|
||||
},
|
||||
reference_no: {
|
||||
label: "Reference No.",
|
||||
column: "reference_no",
|
||||
columnType: "string",
|
||||
label: 'Reference No.',
|
||||
column: 'reference_no',
|
||||
columnType: 'string',
|
||||
},
|
||||
description: {
|
||||
label: "Description",
|
||||
column: "description",
|
||||
columnType: "string",
|
||||
label: 'Description',
|
||||
column: 'description',
|
||||
columnType: 'string',
|
||||
},
|
||||
published: {
|
||||
label: "Published",
|
||||
column: "published_at",
|
||||
label: 'Published',
|
||||
column: 'published_at',
|
||||
},
|
||||
status: {
|
||||
label: 'Status',
|
||||
@@ -194,9 +199,9 @@ export default class Expense extends TenantModel {
|
||||
},
|
||||
},
|
||||
created_at: {
|
||||
label: "Created at",
|
||||
column: "created_at",
|
||||
columnType: "date",
|
||||
label: 'Created at',
|
||||
column: 'created_at',
|
||||
columnType: 'date',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -9,6 +9,21 @@ export default class ExpenseCategory extends TenantModel {
|
||||
return 'expense_transaction_categories';
|
||||
}
|
||||
|
||||
/**
|
||||
* Virtual attributes.
|
||||
*/
|
||||
static get virtualAttributes() {
|
||||
return ['unallocatedLandedCost'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Remain unallocated landed cost.
|
||||
* @return {number}
|
||||
*/
|
||||
get unallocatedLandedCost() {
|
||||
return Math.max(this.amount - this.allocatedCostAmount, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Relationship mapping.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user