- feat: Sales estimates APIs.

- feat: Sales invoices APIs.
- feat: Sales receipts APIs.
- WIP: Sales payment receipts.
- WIP: Purchases bills.
- WIP: Purchases payments made.
This commit is contained in:
Ahmed Bouhuolia
2020-07-22 02:03:12 +02:00
parent 9d9c7c1568
commit 56278a25f0
83 changed files with 5330 additions and 76 deletions

View File

@@ -60,7 +60,7 @@ describe('routes: `/financial_statements`', () => {
// Expense account balance = 1000 | Income account balance = 2000
});
describe.only('routes: `financial_statements/balance_sheet`', () => {
describe('routes: `financial_statements/balance_sheet`', () => {
it('Should response unauthorzied in case the user was not authorized.', async () => {
const res = await request()
.get('/api/financial_statements/balance_sheet')
@@ -111,7 +111,7 @@ describe('routes: `/financial_statements`', () => {
expect(res.body.balance_sheet[1].type).equals('section');
});
it.only('Should retrieve assets and liabilities/equity total of each section.', async () => {
it('Should retrieve assets and liabilities/equity total of each section.', async () => {
const res = await request()
.get('/api/financial_statements/balance_sheet')
.set('x-access-token', loginRes.body.token)

View File

@@ -0,0 +1,113 @@
import {
request,
expect,
} from '~/testInit';
import {
tenantWebsite,
tenantFactory,
loginRes
} from '~/dbInit';
describe('route: `/api/purchases/bill_payments`', () => {
describe('POST: `/api/purchases/bill_payments`', () => {
it('Should `payment_date` be required.', async () => {
const res = await request()
.post('/api/purchases/bills')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'payment_date',
location: 'body',
});
});
it('Should `payment_account_id` be required.', async () => {
const res = await request()
.post('/api/purchases/bills')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'payment_account_id',
location: 'body',
});
});
it('Should `payment_number` be required.', async () => {
const res = await request()
.post('/api/purchases/bills')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'payment_number',
location: 'body',
});
});
it('Should `entries.*.item_id` be required.', async () => {
const res = await request()
.post('/api/purchases/bills')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
entries: [{}],
});
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'entries[0].item_id',
location: 'body',
});
});
it('Should `payment_number` be unique on the storage.', () => {
});
it('Should `payment_account_id` be exists on the storage.', () => {
});
it('Should `entries.*.item_id` be exists on the storage.', () => {
});
it('Should store the given bill payment to the storage.', () => {
});
});
describe('POST: `/api/purchases/bill_payments/:id`', () => {
it('Should bill payment be exists on the storage.', () => {
});
});
describe('DELETE: `/api/purchases/bill_payments/:id`', () => {
it('Should bill payment be exists on the storage.', () => {
});
it('Should delete the given bill payment from the storage.', () => {
});
});
describe('GET: `/api/purchases/bill_payments/:id`', () => {
it('Should bill payment be exists on the storage.', () => {
});
});
});

View File

@@ -0,0 +1,215 @@
import {
request,
expect,
} from '~/testInit';
import {
tenantWebsite,
tenantFactory,
loginRes
} from '~/dbInit';
describe('route: `/api/purchases/bills`', () => {
describe('POST: `/api/purchases/bills`', () => {
it('Should `bill_number` be required.', async () => {
const res = await request()
.post('/api/purchases/bills')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'bill_number',
location: 'body',
});
});
it('Should `vendor_id` be required.', async () => {
const res = await request()
.post('/api/purchases/bills')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'vendor_id',
location: 'body',
});
});
it('Should `bill_date` be required.', async () => {
const res = await request()
.post('/api/purchases/bills')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'bill_date',
location: 'body',
});
});
it('Should `entries` be minimum one', async () => {
const res = await request()
.post('/api/purchases/bills')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'entries',
location: 'body',
});
});
it('Should `entries.*.item_id be required.', async () => {
const res = await request()
.post('/api/purchases/bills')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
entries: [{
}]
});
expect(res.status).equals(422);
expecvt(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'entries[0].item_id',
location: 'body'
});
});
it('Should `entries.*.rate` be required.', async () => {
const res = await request()
.post('/api/purchases/bills')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
entries: [{
}]
});
expect(res.status).equals(422);
expecvt(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'entries[0].rate',
location: 'body'
});
});
it('Should `entries.*.discount` be required.', () => {
});
it('Should entries.*.quantity be required.', () => {
});
it('Should vendor_id be exists on the storage.', async () => {
const vendor = await tenantFactory.create('vendor');
const res = await request()
.post('/api/purchases/bills')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
vendor_id: vendor.id,
bill_number: '123',
bill_date: '2020-02-02',
entries: [{
item_id: 1,
rate: 1,
quantity: 1,
}]
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.deep.equals({
type: 'VENDOR.ID.NOT.FOUND', code: 300,
})
});
it('Should entries.*.item_id be exists on the storage.', async () => {
const item = await tenantFactory.create('item');
const vendor = await tenantFactory.create('vendor');
const res = await request()
.post('/api/purchases/bills')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
vendor_id: vendor.id,
bill_number: '123',
bill_date: '2020-02-02',
entries: [{
item_id: 123123,
rate: 1,
quantity: 1,
}]
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.deep.equals({
type: 'ITEMS.IDS.NOT.FOUND', code: 400,
});
});
it('Should validate the bill number is not exists on the storage.', async () => {
const item = await tenantFactory.create('item');
const vendor = await tenantFactory.create('vendor');
const bill = await tenantFactory.create('bill', { bill_number: '123' });
const res = await request()
.post('/api/purchases/bills')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
vendor_id: vendor.id,
bill_number: '123',
bill_date: '2020-02-02',
entries: [{
item_id: item.id,
rate: 1,
quantity: 1,
}]
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.deep.equals({
type: 'BILL.NUMBER.EXISTS', code: 500,
})
})
it('Should store the given bill details with associated entries to the storage.', async () => {
const item = await tenantFactory.create('item');
const vendor = await tenantFactory.create('vendor');
const res = await request()
.post('/api/purchases/bills')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
vendor_id: vendor.id,
bill_number: '123',
bill_date: '2020-02-02',
entries: [{
item_id: item.id,
rate: 1,
quantity: 1,
}]
});
expect(res.status).equals(200);
});
});
describe('DELETE: `/api/purchases/bills/:id`', () => {
});
});

View File

@@ -0,0 +1,274 @@
import {
request,
expect,
} from '~/testInit';
import {
tenantWebsite,
tenantFactory,
loginRes
} from '~/dbInit';
import {
PaymentReceive,
PaymentReceiveEntry,
} from '@/models';
describe('route: `/sales/payment_receives`', () => {
describe('POST: `/sales/payment_receives`', () => {
it('Should `customer_id` be required.', async () => {
const res = await request()
.post('/api/sales/payment_receives')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'customer_id',
location: 'body',
});
});
it('Should `payment_date` be required.', async () => {
const res = await request()
.post('/api/sales/payment_receives')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'payment_date',
location: 'body',
});
});
it('Should `deposit_account_id` be required.', async () => {
const res = await request()
.post('/api/sales/payment_receives')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'deposit_account_id',
location: 'body',
});
});
it('Should `payment_receive_no` be required.', async () => {
const res = await request()
.post('/api/sales/payment_receives')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'payment_receive_no',
location: 'body',
});
});
it('Should invoices IDs be required.', async () => {
const res = await request()
.post('/api/sales/payment_receives')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'payment_receive_no',
location: 'body',
});
});
it('Should `customer_id` be exists on the storage.', async () => {
const res = await request()
.post('/api/sales/payment_receives')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
customer_id: 123,
payment_date: '2020-02-02',
reference_no: '123',
deposit_account_id: 100,
payment_receive_no: '123',
entries: [
{
invoice_id: 1,
payment_amount: 1000,
}
],
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.deep.equals({
type: 'CUSTOMER.ID.NOT.EXISTS', code: 200,
});
});
it('Should `deposit_account_id` be exists on the storage.', async () => {
const customer = await tenantFactory.create('customer');
const res = await request()
.post('/api/sales/payment_receives')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
customer_id: customer.id,
payment_date: '2020-02-02',
reference_no: '123',
deposit_account_id: 10000,
payment_receive_no: '123',
entries: [
{
invoice_id: 1,
payment_amount: 1000,
}
],
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.deep.equals({
type: 'DEPOSIT.ACCOUNT.NOT.EXISTS', code: 300,
});
});
it('Should invoices IDs be exist on the storage.', async () => {
const customer = await tenantFactory.create('customer');
const account = await tenantFactory.create('account');
const res = await request()
.post('/api/sales/payment_receives')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
customer_id: customer.id,
payment_date: '2020-02-02',
reference_no: '123',
deposit_account_id: account.id,
payment_receive_no: '123',
entries: [
{
invoice_id: 1,
payment_amount: 1000,
}
],
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.deep.equals({
type: 'DEPOSIT.ACCOUNT.NOT.EXISTS', code: 300,
});
});
it('Should payment receive number be unique on the storage.', async () => {
const customer = await tenantFactory.create('customer');
const account = await tenantFactory.create('account');
const paymentReceive = await tenantFactory.create('payment_receive', {
payment_receive_no: '123',
});
const res = await request()
.post('/api/sales/payment_receives')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
customer_id: customer.id,
payment_date: '2020-02-02',
reference_no: '123',
deposit_account_id: account.id,
payment_receive_no: '123',
entries: [
{
invoice_id: 1,
payment_amount: 1000,
}
],
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.deep.equals({
type: 'PAYMENT.RECEIVE.NUMBER.EXISTS', code: 400,
});
});
it('Should store the payment receive details with associated entries.', async () => {
const customer = await tenantFactory.create('customer');
const account = await tenantFactory.create('account');
const invoice = await tenantFactory.create('sale_invoice');
const res = await request()
.post('/api/sales/payment_receives')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
customer_id: customer.id,
payment_date: '2020-02-02',
reference_no: '123',
deposit_account_id: account.id,
payment_receive_no: '123',
entries: [
{
invoice_id: invoice.id,
payment_amount: 1000,
}
],
});
const storedPaymentReceived = await PaymentReceive.tenant().query().where('id', res.body.id).first();
expect(res.status).equals(200);
expect(storedPaymentReceived.customerId).equals(customer.id)
expect(storedPaymentReceived.referenceNo).equals('123');
expect(storedPaymentReceived.paymentReceiveNo).equals('123');
});
});
describe('POST: `/sales/payment_receives/:id`', () => {
it('Should update the payment receive details with associated entries.', async () => {
const paymentReceive = await tenantFactory.create('payment_receive');
const customer = await tenantFactory.create('customer');
const account = await tenantFactory.create('account');
const invoice = await tenantFactory.create('sale_invoice');
const res = await request()
.post(`/api/sales/payment_receives/${paymentReceive.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
customer_id: customer.id,
payment_date: '2020-02-02',
reference_no: '123',
deposit_account_id: account.id,
payment_receive_no: '123',
entries: [
{
invoice_id: invoice.id,
payment_amount: 1000,
}
],
});
expect(res.status).equals(200);
});
});
describe('DELETE: `/sales/payment_receives/:id`', () => {
it('Should response the given payment receive is not exists on the storage.', async () => {
const res = await request()
.delete(`/api/sales/payment_receives/123`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(400);
expect(res.body.errors).include.something.deep.equals({
type: 'PAYMENT.RECEIVE.NO.EXISTS', code: 600,
});
});
});
});

View File

@@ -0,0 +1,439 @@
const { iteratee } = require('lodash');
import { tenantWebsite, tenantFactory, loginRes } from '~/dbInit';
import { request, expect } from '~/testInit';
import { SaleEstimate, SaleEstimateEntry } from '../../src/models';
describe('route: `/sales/estimates`', () => {
describe('POST: `/sales/estimates`', () => {
it('Should `customer_id` be required.', async () => {
const res = await request()
.post('/api/sales/estimates')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'customer_id',
location: 'body',
});
});
it('Should `estimate_date` be required.', async () => {
const res = await request()
.post('/api/sales/estimates')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'estimate_date',
location: 'body',
});
});
it('Should `estimate_number` be required.', async () => {
const res = await request()
.post('/api/sales/estimates')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'estimate_number',
location: 'body',
});
});
it('Should `entries` be atleast one entry.', async () => {
const res = await request()
.post('/api/sales/estimates')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
entries: [],
});
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
value: [],
msg: 'Invalid value',
param: 'entries',
location: 'body',
});
});
it('Should `entries.*.item_id` be required.', async () => {
const res = await request()
.post('/api/sales/estimates')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
entries: [{}],
});
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'entries[0].item_id',
location: 'body',
});
});
it('Should `entries.*.quantity` be required.', async () => {
const res = await request()
.post('/api/sales/estimates')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
entries: [{}],
});
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'entries[0].quantity',
location: 'body',
});
});
it('Should be `entries.*.rate` be required.', async () => {
const res = await request()
.post('/api/sales/estimates')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
entries: [{}],
});
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'entries[0].rate',
location: 'body',
});
});
it('Should `customer_id` be exists on the storage.', async () => {
const res = await request()
.post('/api/sales/estimates')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
customer_id: 10,
estimate_date: '2020-02-02',
expiration_date: '2020-03-03',
estimate_number: '1',
entries: [
{
item_id: 1,
rate: 1,
quantity: 2,
}
],
});
expect(res.status).equals(404);
expect(res.body.errors).include.something.deep.equals({
type: 'CUSTOMER.ID.NOT.FOUND', code: 200,
});
});
it('Should `estimate_number` be unique on the storage.', async () => {
const saleEstimate = await tenantFactory.create('sale_estimate');
const res = await request()
.post('/api/sales/estimates')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
customer_id: saleEstimate.customerId,
estimate_date: '2020-02-02',
expiration_date: '2020-03-03',
estimate_number: saleEstimate.estimateNumber,
entries: [
{
item_id: 1,
rate: 1,
quantity: 2,
}
],
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.deep.equals({
type: 'ESTIMATE.NUMBER.IS.NOT.UNQIUE', code: 300,
});
});
it('Should `entries.*.item_id` be exists on the storage.', async () => {
const customer = await tenantFactory.create('customer');
const res = await request()
.post('/api/sales/estimates')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
customer_id: customer.id,
estimate_date: '2020-02-02',
expiration_date: '2020-03-03',
estimate_number: '12',
entries: [
{
item_id: 1,
rate: 1,
quantity: 2,
}
],
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.deep.equals({
type: 'ITEMS.IDS.NOT.EXISTS', code: 400,
});
});
it('Should store the given details on the storage.', async () => {
const customer = await tenantFactory.create('customer');
const item = await tenantFactory.create('item');
const res = await request()
.post('/api/sales/estimates')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
customer_id: customer.id,
estimate_date: '2020-02-02',
expiration_date: '2020-03-03',
estimate_number: '12',
reference: 'reference',
note: 'note here',
terms_conditions: 'terms and conditions',
entries: [
{
item_id: item.id,
rate: 1,
quantity: 2,
description: 'desc..'
}
],
});
expect(res.status).equals(200);
const storedEstimate = await SaleEstimate.tenant().query().where('id', res.body.id).first();
const storedEstimateEntry = await SaleEstimateEntry.tenant().query().where('estimate_id', res.body.id).first();
expect(storedEstimate.id).equals(res.body.id);
expect(storedEstimate.customerId).equals(customer.id);
expect(storedEstimate.reference).equals('reference')
expect(storedEstimate.note).equals('note here');
expect(storedEstimate.termsConditions).equals('terms and conditions');
expect(storedEstimate.estimateNumber).equals('12');
expect(storedEstimateEntry.itemId).equals(item.id);
expect(storedEstimateEntry.rate).equals(1);
expect(storedEstimateEntry.quantity).equals(2);
expect(storedEstimateEntry.description).equals('desc..');
});
});
describe('DELETE: `/sales/estimates/:id`', () => {
it('Should estimate id be exists on the storage.', async () => {
const estimate = await tenantFactory.create('sale_estimate');
const res = await request()
.delete(`/api/sales/estimates/123`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(404);
expect(res.body.errors).include.something.deep.equals({
type: 'SALE.ESTIMATE.ID.NOT.FOUND', code: 200
});
});
it('Should delete the given estimate with associated entries from the storage.', async () => {
const estimate = await tenantFactory.create('sale_estimate');
const estimateEntry = await tenantFactory.create('sale_estimate_entry', { estimate_id: estimate.id });
const res = await request()
.delete(`/api/sales/estimates/${estimate.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
const foundEstimate = await SaleEstimate.tenant().query().where('id', estimate.id);
const foundEstimateEntry = await SaleEstimateEntry.tenant().query().where('estimate_id', estimate.id);
expect(res.status).equals(200);
expect(foundEstimate.length).equals(0);
expect(foundEstimateEntry.length).equals(0);
});
});
describe('POST: `/sales/estimates/:id`', () => {
it('Should estimate id be exists on the storage.', async () => {
const customer = await tenantFactory.create('customer');
const item = await tenantFactory.create('item');
const res = await request()
.post(`/api/sales/estimates/123`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
customer_id: customer.id,
estimate_date: '2020-02-02',
expiration_date: '2020-03-03',
estimate_number: '12',
reference: 'reference',
note: 'note here',
terms_conditions: 'terms and conditions',
entries: [
{
item_id: item.id,
rate: 1,
quantity: 2,
description: 'desc..'
}
],
})
expect(res.status).equals(404);
expect(res.body.errors).include.something.deep.equals({
type: 'SALE.ESTIMATE.ID.NOT.FOUND', code: 200
});
});
it('Should `entries.*.item_id` be exists on the storage.', async () => {
const saleEstimate = await tenantFactory.create('sale_estimate');
const customer = await tenantFactory.create('customer');
const res = await request()
.post(`/api/sales/estimates/${saleEstimate.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
customer_id: customer.id,
estimate_date: '2020-02-02',
expiration_date: '2020-03-03',
estimate_number: '12',
entries: [
{
item_id: 1,
rate: 1,
quantity: 2,
}
],
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.deep.equals({
type: 'ITEMS.IDS.NOT.EXISTS', code: 400
});
});
it('Should sale estimate number unique on the storage.', async () => {
const saleEstimate = await tenantFactory.create('sale_estimate');
const saleEstimate2 = await tenantFactory.create('sale_estimate');
const res = await request()
.post(`/api/sales/estimates/${saleEstimate.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
customer_id: saleEstimate.customerId,
estimate_date: '2020-02-02',
expiration_date: '2020-03-03',
estimate_number: saleEstimate2.estimateNumber,
entries: [
{
item_id: 1,
rate: 1,
quantity: 2,
}
],
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.deep.equals({
type: 'ESTIMATE.NUMBER.IS.NOT.UNQIUE', code: 300,
});
});
it('Should sale estimate entries IDs be exists on the storage and associated to the sale estimate.', async () => {
const item = await tenantFactory.create('item');
const saleEstimate = await tenantFactory.create('sale_estimate');
const saleEstimate2 = await tenantFactory.create('sale_estimate');
const res = await request()
.post(`/api/sales/estimates/${saleEstimate.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
customer_id: saleEstimate.customerId,
estimate_date: '2020-02-02',
expiration_date: '2020-03-03',
estimate_number: saleEstimate.estimateNumber,
entries: [
{
id: 100,
item_id: item.id,
rate: 1,
quantity: 2,
}
],
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.deep.equals({
type: 'ESTIMATE.NOT.FOUND.ENTRIES.IDS', code: 500,
});
});
it('Should update the given sale estimates with associated entries.', async () => {
const customer = await tenantFactory.create('customer');
const item = await tenantFactory.create('item');
const saleEstimate = await tenantFactory.create('sale_estimate');
const saleEstimateEntry = await tenantFactory.create('sale_estimate_entry', {
estimate_id: saleEstimate.id,
});
const res = await request()
.post(`/api/sales/estimates/${saleEstimate.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
customer_id: customer.id,
estimate_date: '2020-02-02',
expiration_date: '2020-03-03',
estimate_number: '123',
entries: [
{
id: saleEstimateEntry.id,
item_id: item.id,
rate: 100,
quantity: 200,
}
],
});
expect(res.status).equals(200);
});
});
describe('GET: `/sales/estimates`', () => {
it.only('Should retrieve sales estimates.', async () => {
const res = await request()
.get('/api/sales/estimates')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
console.log(res.status, res.body);
});
});
});

View File

@@ -0,0 +1,494 @@
import { tenantWebsite, tenantFactory, loginRes } from '~/dbInit';
import { request, expect } from '~/testInit';
import { SaleInvoice } from '@/models';
import { SaleInvoiceEntry } from '../../src/models';
describe('route: `/sales/invoices`', () => {
describe('POST: `/sales/invoices`', () => {
it('Should `customer_id` be required.', async () => {
const res = await request()
.post('/api/sales/invoices')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'customer_id',
location: 'body',
});
});
it('Should `invoice_date` be required.', async () => {
const res = await request()
.post('/api/sales/invoices')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'invoice_date',
location: 'body',
});
});
it('Should `due_date` be required.', async () => {
const res = await request()
.post('/api/sales/invoices')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'due_date',
location: 'body',
});
});
it('Should `invoice_no` be required.', async () => {
const res = await request()
.post('/api/sales/invoices')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'invoice_no',
location: 'body',
});
});
it('Should `status` be required.', async () => {
const res = await request()
.post('/api/sales/invoices')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'status',
location: 'body',
});
});
it('Should `entries.*.item_id` be required.', async () => {
const res = await request()
.post('/api/sales/invoices')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
entries: [{}],
});
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'entries[0].item_id',
location: 'body',
});
});
it('Should `entries.*.quantity` be required.', async () => {
const res = await request()
.post('/api/sales/invoices')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
entries: [{}],
});
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'entries[0].quantity',
location: 'body',
});
});
it('Should `entries.*.rate` be required.', async () => {
const res = await request()
.post('/api/sales/invoices')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
entries: [{}],
});
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'entries[0].rate',
location: 'body',
});
});
it('Should `customer_id` be exists on the storage.', async () => {
const customer = await tenantFactory.create('customer');
const res = await request()
.post('/api/sales/invoices')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
customer_id: 123,
invoice_date: '2020-02-02',
due_date: '2020-03-03',
invoice_no: '123',
reference_no: '123',
status: 'published',
invoice_message: 'Invoice message...',
terms_conditions: 'terms and conditions',
entries: [
{
item_id: 1,
rate: 1,
quantity: 1,
discount: 1,
}
]
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.deep.equals({
type: 'CUSTOMER.ID.NOT.EXISTS', code: 200,
});
});
it('Should `invoice_date` be bigger than `due_date`.', async () => {
});
it('Should `invoice_no` be unique on the storage.', async () => {
const saleInvoice = await tenantFactory.create('sale_invoice', {
invoice_no: '123',
});
const res = await request()
.post('/api/sales/invoices')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
customer_id: 123,
invoice_date: '2020-02-02',
due_date: '2020-03-03',
invoice_no: '123',
reference_no: '123',
status: 'published',
invoice_message: 'Invoice message...',
terms_conditions: 'terms and conditions',
entries: [
{
item_id: 1,
rate: 1,
quantity: 1,
discount: 1,
}
]
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.deep.equals({
type: 'SALE.INVOICE.NUMBER.IS.EXISTS', code: 200
});
});
it('Should `entries.*.item_id` be exists on the storage.', async () => {
const res = await request()
.post('/api/sales/invoices')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
customer_id: 123,
invoice_date: '2020-02-02',
due_date: '2020-03-03',
invoice_no: '123',
reference_no: '123',
status: 'published',
invoice_message: 'Invoice message...',
terms_conditions: 'terms and conditions',
entries: [
{
item_id: 1,
rate: 1,
quantity: 1,
discount: 1,
}
]
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.deep.equals({
type: 'ITEMS.IDS.NOT.EXISTS', code: 300,
});
});
it('Should save the given sale invoice details with associated entries.', async () => {
const customer = await tenantFactory.create('customer');
const item = await tenantFactory.create('item');
const res = await request()
.post('/api/sales/invoices')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
customer_id: customer.id,
invoice_date: '2020-02-02',
due_date: '2020-03-03',
invoice_no: '123',
reference_no: '123',
status: 'published',
invoice_message: 'Invoice message...',
terms_conditions: 'terms and conditions',
entries: [
{
item_id: item.id,
rate: 1,
quantity: 1,
discount: 1,
}
]
});
expect(res.status).equals(200);
});
});
describe('POST: `/api/sales/invoices/:id`', () => {
it('Should `customer_id` be required.', async () => {
const res = await request()
.post('/api/sales/invoices/123')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'customer_id',
location: 'body',
});
});
it('Should `invoice_date` be required.', async () => {
const res = await request()
.post('/api/sales/invoices/123')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'invoice_date',
location: 'body',
});
});
it('Should `status` be required.', async () => {
const res = await request()
.post('/api/sales/invoices/123')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'status',
location: 'body',
});
});
it('Should `entries.*.item_id` be required.', async () => {
const res = await request()
.post('/api/sales/invoices/123')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
entries: [{}],
});
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'entries[0].item_id',
location: 'body',
});
});
it('Should `entries.*.quantity` be required.', async () => {
const res = await request()
.post('/api/sales/invoices/123')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
entries: [{}],
});
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'entries[0].quantity',
location: 'body',
});
});
it('Should `entries.*.rate` be required.', async () => {
const res = await request()
.post('/api/sales/invoices/123')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
entries: [{}],
});
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'entries[0].rate',
location: 'body',
});
});
it('Should `customer_id` be exists on the storage.', async () => {
const customer = await tenantFactory.create('customer');
const saleInvoice = await tenantFactory.create('sale_invoice');
const res = await request()
.post(`/api/sales/invoices/${saleInvoice.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
customer_id: 123,
invoice_date: '2020-02-02',
due_date: '2020-03-03',
invoice_no: '123',
reference_no: '123',
status: 'published',
invoice_message: 'Invoice message...',
terms_conditions: 'terms and conditions',
entries: [
{
item_id: 1,
rate: 1,
quantity: 1,
discount: 1,
}
]
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.deep.equals({
type: 'CUSTOMER.ID.NOT.EXISTS', code: 200,
});
});
it('Should `invoice_date` be bigger than `due_date`.', async () => {
});
it('Should `invoice_no` be unique on the storage.', async () => {
const saleInvoice = await tenantFactory.create('sale_invoice', {
invoice_no: '123',
});
const res = await request()
.post('/api/sales/invoices')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
customer_id: 123,
invoice_date: '2020-02-02',
due_date: '2020-03-03',
invoice_no: '123',
reference_no: '123',
status: 'published',
invoice_message: 'Invoice message...',
terms_conditions: 'terms and conditions',
entries: [
{
item_id: 1,
rate: 1,
quantity: 1,
discount: 1,
}
]
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.deep.equals({
type: 'SALE.INVOICE.NUMBER.IS.EXISTS', code: 200
});
});
it('Should update the sale invoice details with associated entries.', async () => {
const saleInvoice = await tenantFactory.create('sale_invoice');
const customer = await tenantFactory.create('customer');
const item = await tenantFactory.create('item');
const res = await request()
.post(`/api/sales/invoices/${saleInvoice.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
customer_id: customer.id,
invoice_date: '2020-02-02',
due_date: '2020-03-03',
invoice_no: '1',
reference_no: '123',
status: 'published',
invoice_message: 'Invoice message...',
terms_conditions: 'terms and conditions',
entries: [
{
item_id: item.id,
rate: 1,
quantity: 1,
discount: 1,
}
]
});
expect(res.status).equals(200);
});
});
describe('DELETE: `/sales/invoices/:id`', () => {
it('Should retrieve sale invoice not found.', async () => {
const res = await request()
.delete('/api/sales/invoices/123')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(404);
expect(res.body.errors).include.something.deep.equals({
type: 'SALE.INVOICE.NOT.FOUND', code: 200,
});
});
it('Should delete the given sale invoice with assocaited entries.', async () => {
const saleInvoice = await tenantFactory.create('sale_invoice');
const saleInvoiceEntey = await tenantFactory.create('sale_invoice_entry', {
sale_invoice_id: saleInvoice.id,
});
const res = await request()
.delete(`/api/sales/invoices/${saleInvoice.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
const storedSaleInvoice = await SaleInvoice.tenant().query().where('id', saleInvoice.id);
const storedSaleInvoiceEntry = await SaleInvoiceEntry.tenant().query().where('id', saleInvoiceEntey.id);
expect(res.status).equals(200);
expect(storedSaleInvoice.length).equals(0);
expect(storedSaleInvoiceEntry.length).equals(0);
});
});
});

View File

@@ -0,0 +1,294 @@
import { tenantWebsite, tenantFactory, loginRes } from '~/dbInit';
import { request, expect } from '~/testInit';
import { SaleReceipt } from '@/models';
describe('route: `/sales/receipts`', () => {
describe('POST: `/sales/receipts`', () => {
it('Should `deposit_account_id` be required.', async () => {
const res = await request()
.post('/api/sales/receipts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'deposit_account_id',
location: 'body',
});
});
it('Should `customer_id` be required.', async () => {
const res = await request()
.post('/api/sales/receipts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'customer_id',
location: 'body',
});
});
it('should `receipt_date` be required.', async () => {
const res = await request()
.post('/api/sales/receipts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value',
param: 'receipt_date',
location: 'body',
});
});
it('Should `entries.*.item_id` be required.', async () => {});
it('Should `deposit_account_id` be exists.', async () => {
const res = await request()
.post('/api/sales/receipts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
deposit_account_id: 12220,
customer_id: 1,
receipt_date: '2020-02-02',
reference_no: '123',
entries: [
{
item_id: 1,
quantity: 1,
rate: 2,
},
],
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.deep.equals({
type: 'DEPOSIT.ACCOUNT.NOT.EXISTS',
code: 300,
});
});
it('Should `customer_id` be exists.', async () => {
const res = await request()
.post('/api/sales/receipts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
deposit_account_id: 12220,
customer_id: 1001,
receipt_date: '2020-02-02',
reference_no: '123',
entries: [
{
item_id: 1,
quantity: 1,
rate: 2,
},
],
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.deep.equals({
type: 'CUSTOMER.ID.NOT.EXISTS',
code: 200,
});
});
it('Should all `entries.*.item_id` be exists on the storage.', async () => {
const res = await request()
.post('/api/sales/receipts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
deposit_account_id: 12220,
customer_id: 1001,
receipt_date: '2020-02-02',
reference_no: '123',
entries: [
{
item_id: 1000,
quantity: 1,
rate: 2,
},
],
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.deep.equals({
type: 'ITEMS.IDS.NOT.EXISTS',
code: 400,
});
});
it('Should store the sale receipt details with entries to the storage.', async () => {
const item = await tenantFactory.create('item');
const customer = await tenantFactory.create('customer');
const account = await tenantFactory.create('account');
const res = await request()
.post('/api/sales/receipts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
deposit_account_id: account.id,
customer_id: customer.id,
receipt_date: '2020-02-02',
reference_no: '123',
receipt_message: 'Receipt message...',
statement: 'Receipt statement...',
entries: [
{
item_id: item.id,
quantity: 1,
rate: 2,
},
],
});
const storedSaleReceipt = await SaleReceipt.tenant()
.query()
.where('id', res.body.id)
.first();
expect(res.status).equals(200);
expect(storedSaleReceipt.depositAccountId).equals(account.id);
expect(storedSaleReceipt.referenceNo).equals('123');
expect(storedSaleReceipt.customerId).equals(customer.id);
expect(storedSaleReceipt.receiptMessage).equals('Receipt message...');
expect(storedSaleReceipt.statement).equals('Receipt statement...');
});
});
describe('DELETE: `/sales/receipts/:id`', () => {
it('Should the given sale receipt id be exists on the storage.', async () => {
const res = await request()
.delete('/api/sales/receipts/123')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(404);
expect(res.body.errors).include.something.deep.equals({
type: 'SALE.RECEIPT.NOT.FOUND',
code: 200,
});
});
it('Should delete the sale receipt with associated entries and journal transactions.', async () => {
const saleReceipt = await tenantFactory.create('sale_receipt');
const saleReceiptEntry = await tenantFactory.create(
'sale_receipt_entry',
{
sale_receipt_id: saleReceipt.id,
}
);
const res = await request()
.delete(`/api/sales/receipts/${saleReceipt.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
const storedSaleReceipt = await SaleReceipt.tenant()
.query()
.where('id', saleReceipt.id);
const storedSaleReceiptEntries = await SaleReceipt.tenant()
.query()
.where('id', saleReceiptEntry.id);
expect(res.status).equals(200);
expect(storedSaleReceipt.length).equals(0);
expect(storedSaleReceiptEntries.length).equals(0);
});
});
describe('POST: `/sales/receipts/:id`', () => {
it('Should the given sale receipt id be exists on the storage.', async () => {
const res = await request()
.post('/api/sales/receipts/123')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
deposit_account_id: 123,
customer_id: 123,
receipt_date: '2020-02-02',
reference_no: '123',
receipt_message: 'Receipt message...',
statement: 'Receipt statement...',
entries: [
{
item_id: 123,
quantity: 1,
rate: 2,
},
],
});
expect(res.status).equals(404);
expect(res.body.errors).include.something.deep.equals({
type: 'SALE.RECEIPT.NOT.FOUND',
code: 200,
});
});
it('Should update the sale receipt details with associated entries.', async () => {
const saleReceipt = await tenantFactory.create('sale_receipt');
const depositAccount = await tenantFactory.create('account');
const customer = await tenantFactory.create('customer');
const item = await tenantFactory.create('item');
const res = await request()
.post(`/api/sales/receipts/${saleReceipt.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
deposit_account_id: depositAccount.id,
customer_id: customer.id,
receipt_date: '2020-02-02',
reference_no: '123',
receipt_message: 'Receipt message...',
statement: 'Receipt statement...',
entries: [
{
id: 100,
item_id: item.id,
quantity: 1,
rate: 2,
},
],
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.deep.equals({
type: 'ENTRIES.IDS.NOT.FOUND', code: 500,
});
});
});
describe('GET: `/sales/receipts`', () => {
it('Should response the custom view id not exists on the storage.', async () => {
const res = await request()
.get('/api/sales/receipts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
});
console.log(res.status, res.body);
});
it('Should retrieve all sales receipts on the storage with pagination meta.', () => {
});
});
});

View File

@@ -76,6 +76,16 @@ describe('JournalPoster', () => {
});
});
describe('setContactAccountBalance', () => {
it('Should increment balance amount after credit/debit entry.', () => {
});
it('Should decrement balance amount after credit/debit customer/vendor entry.', () => {
});
});
describe('saveEntries()', () => {
it('Should save all stacked entries to the storage.', async () => {
const journalEntries = new JournalPoster(accountsDepGraph);