add customer end point , update sales to more detail

pull/1/head
Aji Kamaludin 3 years ago
parent 97a5cb21d9
commit 09bfda51c7
No known key found for this signature in database
GPG Key ID: 670E1F26AD5A8099

@ -1072,7 +1072,7 @@
" pm.expect(responseJson).to.haveOwnProperty('status');", " pm.expect(responseJson).to.haveOwnProperty('status');",
" pm.expect(responseJson.status).to.equals('success');", " pm.expect(responseJson.status).to.equals('success');",
"", "",
" pm.environment.set('unitId', '')", " pm.environment.set('categoryId', '')",
"})" "})"
], ],
"type": "text/javascript" "type": "text/javascript"
@ -1107,6 +1107,293 @@
} }
] ]
}, },
{
"name": "Customers",
"item": [
{
"name": "add customer",
"event": [
{
"listen": "test",
"script": {
"exec": [
"pm.test('test status code', () => {",
" pm.response.to.have.status(201)",
"});",
"",
"pm.test('test data', () => {",
" const responseJson = pm.response.json();",
"",
" pm.expect(responseJson).to.haveOwnProperty('status');",
" pm.expect(responseJson.status).to.equals('success');",
"",
" pm.environment.set('customerId', responseJson.data.customerId)",
"})"
],
"type": "text/javascript"
}
}
],
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{accessToken}}",
"type": "string"
}
]
},
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\n \"name\": \"pelanggan 1\",\n \"phone\": \"083\",\n \"address\": \"klaten\",\n \"description\": \"-\"\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{host}}/customers",
"host": [
"{{host}}"
],
"path": [
"customers"
]
}
},
"response": []
},
{
"name": "get customer",
"event": [
{
"listen": "test",
"script": {
"exec": [
"pm.test('test status code', () => {",
" pm.response.to.have.status(200)",
"});",
"",
"pm.test('test data', () => {",
" const responseJson = pm.response.json();",
"",
" pm.expect(responseJson).to.haveOwnProperty('status');",
" pm.expect(responseJson.status).to.equals('success');",
"})"
],
"type": "text/javascript"
}
}
],
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{accessToken}}",
"type": "string"
}
]
},
"method": "GET",
"header": [],
"url": {
"raw": "{{host}}/customers/{{customerId}}",
"host": [
"{{host}}"
],
"path": [
"customers",
"{{customerId}}"
]
}
},
"response": []
},
{
"name": "get customers",
"event": [
{
"listen": "prerequest",
"script": {
"exec": [
"var moment = require('moment');",
"",
"pm.environment.set('currentdate', moment().format((\"YYYY-MM-DD\")));",
"pm.environment.set('futuredate', moment().add(5, 'days').format((\"YYYY-MM-DD\")))"
],
"type": "text/javascript"
}
},
{
"listen": "test",
"script": {
"exec": [
"pm.test('test status code', () => {",
" pm.response.to.have.status(200)",
"});",
"",
"pm.test('test data', () => {",
" const responseJson = pm.response.json();",
"",
" pm.expect(responseJson).to.haveOwnProperty('status');",
" pm.expect(responseJson.status).to.equals('success');",
"})"
],
"type": "text/javascript"
}
}
],
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{accessToken}}",
"type": "string"
}
]
},
"method": "GET",
"header": [],
"url": {
"raw": "{{host}}/customers?page=1&q=p",
"host": [
"{{host}}"
],
"path": [
"customers"
],
"query": [
{
"key": "page",
"value": "1"
},
{
"key": "q",
"value": "p"
}
]
}
},
"response": []
},
{
"name": "update customer",
"event": [
{
"listen": "test",
"script": {
"exec": [
"pm.test('test status code', () => {",
" pm.response.to.have.status(200)",
"});",
"",
"pm.test('test data', () => {",
" const responseJson = pm.response.json();",
"",
" pm.expect(responseJson).to.haveOwnProperty('status');",
" pm.expect(responseJson.status).to.equals('success');",
"})"
],
"type": "text/javascript"
}
}
],
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{accessToken}}",
"type": "string"
}
]
},
"method": "PUT",
"header": [],
"body": {
"mode": "raw",
"raw": "{\n \"name\": \"pelanggan 1 update\",\n \"phone\": \"083\",\n \"address\": \"klaten\",\n \"description\": \"update\"\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{host}}/customers/{{customerId}}",
"host": [
"{{host}}"
],
"path": [
"customers",
"{{customerId}}"
]
}
},
"response": []
},
{
"name": "delete customer",
"event": [
{
"listen": "test",
"script": {
"exec": [
"pm.test('test status code', () => {",
" pm.response.to.have.status(200)",
"});",
"",
"pm.test('test data', () => {",
" const responseJson = pm.response.json();",
"",
" pm.expect(responseJson).to.haveOwnProperty('status');",
" pm.expect(responseJson.status).to.equals('success');",
"",
" pm.environment.set('customerId', '')",
"})"
],
"type": "text/javascript"
}
}
],
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{accessToken}}",
"type": "string"
}
]
},
"method": "DELETE",
"header": [],
"url": {
"raw": "{{host}}/customers/{{customerId}}",
"host": [
"{{host}}"
],
"path": [
"customers",
"{{customerId}}"
]
}
},
"response": []
}
]
},
{ {
"name": "Products", "name": "Products",
"item": [ "item": [
@ -1138,7 +1425,7 @@
"script": { "script": {
"exec": [ "exec": [
"const createProduct1Request = {", "const createProduct1Request = {",
" url: 'http://localhost:5000/categories',", " url: `${pm.environment.get('host')}/categories`,",
" method: 'POST',", " method: 'POST',",
" header: {", " header: {",
" 'Content-Type': 'application/json',", " 'Content-Type': 'application/json',",
@ -1437,6 +1724,50 @@
{ {
"name": "Transaction", "name": "Transaction",
"item": [ "item": [
{
"name": "pre runner [required for runner]",
"event": [
{
"listen": "prerequest",
"script": {
"exec": [
"const createCustomerRequest = {",
" url: `${pm.environment.get('host')}/categories`,",
" method: 'POST',",
" header: {",
" 'Content-Type': 'application/json',",
" 'Authorization': `Bearer ${pm.environment.get('accessToken')}`",
" },",
" body: {",
" mode: 'raw',",
" raw: JSON.stringify({",
" name: \"category one\",",
" }),",
" },",
"};",
" ",
"pm.sendRequest(createCustomerRequest, (error, response) => {",
" console.log(error ? error : response);",
" const result = response.json()",
" pm.environment.set('categoryId', result.data.categoryId)",
"});"
],
"type": "text/javascript"
}
}
],
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{host}}",
"host": [
"{{host}}"
]
}
},
"response": []
},
{ {
"name": "sale", "name": "sale",
"event": [ "event": [
@ -1444,8 +1775,29 @@
"listen": "prerequest", "listen": "prerequest",
"script": { "script": {
"exec": [ "exec": [
"const createCustomerRequest = {",
" url: `${pm.environment.get('host')}/customers`,",
" method: 'POST',",
" header: {",
" 'Content-Type': 'application/json',",
" 'Authorization': `Bearer ${pm.environment.get('accessToken')}`",
" },",
" body: {",
" mode: 'raw',",
" raw: JSON.stringify({",
" name: \"customer one\",",
" }),",
" },",
"};",
" ",
"pm.sendRequest(createCustomerRequest, (error, response) => {",
" console.log(error ? error : response);",
" const result = response.json()",
" pm.environment.set('customerId', result.data.customerId)",
"});",
"",
"const createProduct1Request = {", "const createProduct1Request = {",
" url: 'http://localhost:5000/products',", " url: `${pm.environment.get('host')}/products`,",
" method: 'POST',", " method: 'POST',",
" header: {", " header: {",
" 'Content-Type': 'application/json',", " 'Content-Type': 'application/json',",
@ -1470,7 +1822,7 @@
"});", "});",
"", "",
"const createProduct2Request = {", "const createProduct2Request = {",
" url: 'http://localhost:5000/products',", " url: `${pm.environment.get('host')}/products`,",
" method: 'POST',", " method: 'POST',",
" header: {", " header: {",
" 'Content-Type': 'application/json',", " 'Content-Type': 'application/json',",
@ -1539,7 +1891,7 @@
"header": [], "header": [],
"body": { "body": {
"mode": "raw", "mode": "raw",
"raw": "{\n \"officeId\": \"{{officeId}}\",\n \"date\": \"{{currentdate}}\",\n \"invoice\": \"test\",\n \"amount\": 2000,\n \"discount\": 0,\n \"description\": \"test saja\",\n \"items\" : [\n {\n \"productId\": \"{{productId-1}}\",\n \"quantity\": 1,\n \"price\": 2000\n },\n {\n \"productId\": \"{{productId-2}}\",\n \"quantity\": 1,\n \"price\": 4000\n }\n ]\n}", "raw": "{\n \"officeId\": \"{{officeId}}\",\n \"customerId\": \"{{customerId}}\",\n \"date\": \"{{currentdate}}\",\n \"invoice\": \"test\",\n \"amount\": 2000,\n \"discount\": 0,\n \"description\": \"test saja\",\n \"items\" : [\n {\n \"productId\": \"{{productId-1}}\",\n \"quantity\": 1,\n \"price\": 2000\n },\n {\n \"productId\": \"{{productId-2}}\",\n \"quantity\": 1,\n \"price\": 4000\n }\n ]\n}",
"options": { "options": {
"raw": { "raw": {
"language": "json" "language": "json"
@ -1683,7 +2035,7 @@
"script": { "script": {
"exec": [ "exec": [
"const createProduct1Request = {", "const createProduct1Request = {",
" url: 'http://localhost:5000/products',", " url: `${pm.environment.get('host')}/products`,",
" method: 'POST',", " method: 'POST',",
" header: {", " header: {",
" 'Content-Type': 'application/json',", " 'Content-Type': 'application/json',",
@ -1708,7 +2060,7 @@
"});", "});",
"", "",
"const createProduct2Request = {", "const createProduct2Request = {",
" url: 'http://localhost:5000/products',", " url: `${pm.environment.get('host')}/products`,",
" method: 'POST',", " method: 'POST',",
" header: {", " header: {",
" 'Content-Type': 'application/json',", " 'Content-Type': 'application/json',",

@ -91,9 +91,14 @@
"key": "purchaseId", "key": "purchaseId",
"value": "", "value": "",
"enabled": true "enabled": true
},
{
"key": "customerId",
"value": "",
"enabled": true
} }
], ],
"_postman_variable_scope": "environment", "_postman_variable_scope": "environment",
"_postman_exported_at": "2021-08-09T14:04:30.468Z", "_postman_exported_at": "2021-08-19T14:21:24.373Z",
"_postman_exported_using": "Postman/8.10.0" "_postman_exported_using": "Postman/8.10.0"
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

After

Width:  |  Height:  |  Size: 155 KiB

@ -248,9 +248,57 @@ exports.up = (pgm) => {
], ],
}, },
}); });
pgm.createTable('customers', {
id: {
type: 'uuid',
primaryKey: true,
},
name: {
type: 'varchar(255)',
notNull: true,
},
phone: {
type: 'varchar(16)',
notNull: false,
},
address: {
type: 'text',
notNull: false,
},
description: {
type: 'text',
notNull: false,
},
company_id: {
type: 'uuid',
notNull: true,
},
created_at: {
type: 'timestamp without time zone',
notNull: true,
default: pgm.func('current_timestamp'),
},
updated_at: {
type: 'timestamp without time zone',
notNull: true,
default: pgm.func('current_timestamp'),
},
}, {
constraints: {
foreignKeys: [
{
references: 'companies(id)',
columns: 'company_id',
onDelete: 'CASCADE',
},
],
},
});
}; };
exports.down = (pgm) => { exports.down = (pgm) => {
pgm.dropTable('customers');
pgm.dropTable('prices'); pgm.dropTable('prices');
pgm.dropTable('stocks'); pgm.dropTable('stocks');
pgm.dropTable('products'); pgm.dropTable('products');

@ -31,6 +31,10 @@ exports.up = (pgm) => {
type: 'numeric(16,2)', type: 'numeric(16,2)',
notNull: false, notNull: false,
}, },
customer_id: {
type: 'uuid',
notNull: true,
},
created_by: { created_by: {
type: 'uuid', type: 'uuid',
notNull: true, notNull: true,
@ -58,6 +62,11 @@ exports.up = (pgm) => {
columns: 'created_by', columns: 'created_by',
onDelete: 'CASCADE', onDelete: 'CASCADE',
}, },
{
references: 'customers(id)',
columns: 'customer_id',
onDelete: 'CASCADE',
},
], ],
}, },
}); });

@ -69,6 +69,7 @@ class CategoriesHandler {
async putCategoriesHandler(request) { async putCategoriesHandler(request) {
try { try {
this._validator.validatePostCategoryPayload(request.payload);
const { id: categoryId } = request.params; const { id: categoryId } = request.params;
const { name, description } = request.payload; const { name, description } = request.payload;

@ -0,0 +1,105 @@
class CustomersHandler {
constructor(service, validator) {
this._service = service;
this._validator = validator;
this.postCustomerHandler = this.postCustomerHandler.bind(this);
this.getCustomersHandler = this.getCustomersHandler.bind(this);
this.getCustomerByIdHandler = this.getCustomerByIdHandler.bind(this);
this.putCustomerByIdHandler = this.putCustomerByIdHandler.bind(this);
this.deleteCustomerByIdHandler = this.deleteCustomerByIdHandler.bind(this);
}
async postCustomerHandler(request, h) {
try {
this._validator.validatePostCustomerPayload(request.payload);
const { companyId } = request.auth.credentials;
const { name, phone, address, description } = request.payload;
const customerId = await this._service.addCustomer({
name, phone, address, description, companyId,
});
const response = h.response({
status: 'success',
message: 'Customer berhasil ditambahkan',
data: {
customerId,
name,
},
});
response.code(201);
return response;
} catch (error) {
return error;
}
}
async getCustomersHandler(request) {
try {
const { companyId } = request.auth.credentials;
const { page, q } = request.query;
const { customers, meta } = await this._service.getCustomers(companyId, { page, q });
return {
status: 'success',
data: { customers, meta },
};
} catch (error) {
return error;
}
}
async getCustomerByIdHandler(request) {
try {
const { id: customerId } = request.params;
const customer = await this._service.getCustomerById(customerId);
return {
status: 'success',
data: {
customer,
},
};
} catch (error) {
return error;
}
}
async putCustomerByIdHandler(request) {
try {
this._validator.validatePostCustomerPayload(request.payload);
const { id: customerId } = request.params;
const { name, phone, address, description } = request.payload;
await this._service.updateCustomerById(customerId, { name, phone, address, description });
return {
status: 'success',
data: {
name,
},
};
} catch (error) {
return error;
}
}
async deleteCustomerByIdHandler(request) {
try {
const { id: customerId } = request.params;
await this._service.deleteCustomerById(customerId);
return {
status: 'success',
data: {},
};
} catch (error) {
return error;
}
}
}
module.exports = CustomersHandler;

@ -0,0 +1,11 @@
const CustomersHandler = require('./handler');
const routes = require('./routes');
module.exports = {
name: 'customers',
version: '1.0.0',
register: async (server, { service, validator }) => {
const customersHandler = new CustomersHandler(service, validator);
server.route(routes(customersHandler));
},
};

@ -0,0 +1,44 @@
const routes = (handler) => [
{
method: 'POST',
path: '/customers',
handler: handler.postCustomerHandler,
options: {
auth: 'kasiraja_jwt',
},
},
{
method: 'GET',
path: '/customers',
handler: handler.getCustomersHandler,
options: {
auth: 'kasiraja_jwt',
},
},
{
method: 'GET',
path: '/customers/{id}',
handler: handler.getCustomerByIdHandler,
options: {
auth: 'kasiraja_jwt',
},
},
{
method: 'PUT',
path: '/customers/{id}',
handler: handler.putCustomerByIdHandler,
options: {
auth: 'kasiraja_jwt',
},
},
{
method: 'DELETE',
path: '/customers/{id}',
handler: handler.deleteCustomerByIdHandler,
options: {
auth: 'kasiraja_jwt',
},
},
];
module.exports = routes;

@ -13,11 +13,11 @@ class SalesHandler {
this._validator.validatePostSalePayload(request.payload); this._validator.validatePostSalePayload(request.payload);
const { id: userId } = request.auth.credentials; const { id: userId } = request.auth.credentials;
const { const {
date, invoice, description, amount, discount, items, officeId, date, invoice, description, amount, discount, items, officeId, customerId
} = request.payload; } = request.payload;
const saleId = await this._service.createTransaction({ const saleId = await this._service.createTransaction({
date, invoice, description, amount, discount, items, userId, officeId, date, invoice, description, amount, discount, items, userId, officeId, customerId
}); });
const response = h.response({ const response = h.response({
@ -39,14 +39,19 @@ class SalesHandler {
this._validator.validateGetSalesPayload(request.query); this._validator.validateGetSalesPayload(request.query);
const { companyId } = request.auth.credentials; const { companyId } = request.auth.credentials;
const { startDate, endDate } = request.query; const {
startDate, endDate, page, q, customerId,
} = request.query;
const sales = await this._service.getSales(companyId, { startDate, endDate }); const { sales, meta } = await this._service.getSales(companyId, {
startDate, endDate, page, q, customerId,
});
return { return {
status: 'success', status: 'success',
data: { data: {
sales, sales,
meta,
}, },
}; };
} catch (error) { } catch (error) {

@ -30,6 +30,11 @@ const categories = require('./api/categories');
const CategoriesService = require('./services/postgres/CategoriesService'); const CategoriesService = require('./services/postgres/CategoriesService');
const CategoriesValidator = require('./validator/categories'); const CategoriesValidator = require('./validator/categories');
// customers
const customers = require('./api/customers');
const CustomersService = require('./services/postgres/CustomersService');
const CustomerValidator = require('./validator/customers');
// products // products
const products = require('./api/products'); const products = require('./api/products');
const ProductsService = require('./services/postgres/ProductsService'); const ProductsService = require('./services/postgres/ProductsService');
@ -52,6 +57,7 @@ const init = async () => {
const registrationsService = new RegistrationsService(usersService); const registrationsService = new RegistrationsService(usersService);
const unitsService = new UnitsService(); const unitsService = new UnitsService();
const categoriesService = new CategoriesService(); const categoriesService = new CategoriesService();
const customersService = new CustomersService();
const productsService = new ProductsService(); const productsService = new ProductsService();
const salesService = new SalesService(); const salesService = new SalesService();
const purchasesService = new PurchasesService(); const purchasesService = new PurchasesService();
@ -169,6 +175,13 @@ const init = async () => {
service: unitsService, service: unitsService,
}, },
}, },
{
plugin: customers,
options: {
service: customersService,
validator: CustomerValidator,
},
},
{ {
plugin: products, plugin: products,
options: { options: {

@ -0,0 +1,100 @@
const { Pool } = require('pg');
const uuid = require('uuid-random');
const NotFoundError = require('../../exceptions/NotFoundError');
const { validateUuid } = require('../../utils');
class CustomersService {
constructor() {
this._pool = new Pool();
}
async getCustomers(companyId, { page = 1, limit = 10, q = null }) {
const recordsQuery = await this._pool.query(`
SELECT count(id) as total
FROM customers
WHERE
company_id = '${companyId}'
${q !== null ? `AND name ILIKE '%${q}%'` : ''}
`);
const { total } = recordsQuery.rows[0];
const totalPages = Math.ceil(total / limit);
const offsets = limit * (page - 1);
const query = {
text: `
SELECT id, name, phone, description
FROM customers
WHERE company_id = $1
${q !== null ? `AND name ILIKE '%${q}%' OR phone ILIKE '%${q}%'` : ''}
ORDER BY created_at DESC
LIMIT $2 OFFSET $3`,
values: [companyId, limit, offsets],
};
const { rows } = await this._pool.query(query);
return {
customers: rows,
meta: {
totalPages,
total,
page,
},
};
}
async getCustomerById(customerId) {
validateUuid(customerId);
const query = {
text: 'SELECT name, phone, address, description FROM customers WHERE id = $1',
values: [customerId],
};
const results = await this._pool.query(query);
if (results.rowCount < 1) {
throw new NotFoundError('Customer tidak ditemukan');
}
return results.rows[0];
}
async addCustomer({ name, phone, address, description, companyId }) {
const id = uuid();
const query = {
text: 'INSERT INTO customers(id, name, phone, address, description, company_id) VALUES ($1, $2, $3, $4, $5, $6)',
values: [id, name, phone, address, description, companyId],
};
await this._pool.query(query);
return id;
}
async updateCustomerById(customerId, { name, phone, address, description }) {
validateUuid(customerId);
const query = {
text: 'UPDATE customers SET name = $1, phone = $2, address = $3, description = $4 WHERE id = $5',
values: [name, phone, address, description, customerId],
};
await this._pool.query(query);
}
async deleteCustomerById(customerId) {
validateUuid(customerId);
const query = {
text: 'DELETE FROM customers WHERE id = $1',
values: [customerId],
};
await this._pool.query(query);
}
}
module.exports = CustomersService;

@ -43,18 +43,25 @@ class RegistrationService {
values: [unitId, 'Buah', companyId], values: [unitId, 'Buah', companyId],
}; };
const createCustomerQuery = {
text: 'INSERT INTO customers(id, name, phone, address, description, company_id) VALUES ((select uuid_generate_v4()), $1, $2, $3, $4, $5)',
values: ['Pelanggan Umum', '089', 'Klaten', '-', companyId]
}
const client = await this._pool.connect();
try { try {
await this._pool.query('BEGIN'); await client.query('BEGIN');
await this._pool.query(createCompanyQuery); await client.query(createCompanyQuery);
await this._pool.query(createOfficeQuery); await client.query(createOfficeQuery);
await this._pool.query(createWarehouseQuery); await client.query(createWarehouseQuery);
await this._pool.query(createUserQuery); await client.query(createUserQuery);
await this._pool.query(createUnitQuery); await client.query(createUnitQuery);
await this._pool.query('COMMIT'); await client.query('COMMIT');
} catch (err) { } catch (err) {
await this._pool.query('ROLLBACK'); await client.query('ROLLBACK');
console.log(err); throw new InvariantError(`Gagal melakukan registrasi: ${err.message}`);
throw new InvariantError('Gagal melakukan registrasi'); } finally {
client.release();
} }
} }
} }

@ -10,7 +10,7 @@ class SalesService {
} }
async createTransaction({ async createTransaction({
date, invoice, description, amount, discount, items, userId, officeId, date, invoice, description, amount, discount, items, userId, officeId, customerId,
}) { }) {
// check stock // check stock
const stocksQuery = await this._pool.query(` const stocksQuery = await this._pool.query(`
@ -35,9 +35,9 @@ class SalesService {
const id = uuid(); const id = uuid();
const saleQuery = { const saleQuery = {
text: `INSERT INTO text: `INSERT INTO
sales(id, date, invoice, description, amount, discount, created_by, office_id) sales(id, date, invoice, description, amount, discount, created_by, office_id, customer_id)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING id`, VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING id`,
values: [id, date, invoice, description, amount, discount, userId, officeId], values: [id, date, invoice, description, amount, discount, userId, officeId, customerId],
}; };
const sale = await client.query(saleQuery); const sale = await client.query(saleQuery);
@ -64,22 +64,52 @@ class SalesService {
} }
} }
async getSales(companyId, { startDate, endDate }) { async getSales(companyId, {
startDate, endDate, page = 1, q = null, customerId, limit = 20,
}) {
const recordsQuery = await this._pool.query(`
SELECT count(sales.id) as total
FROM sales
${customerId ? `LEFT JOIN customers ON customers.id = sales.customer_id` : ''}
WHERE
sales.office_id = (SELECT id FROM offices WHERE company_id = '${companyId}' LIMIT 1)
${q ? `AND invoice ILIKE '%${q}%'` : ''}
${customerId ? `AND customer_id = '${customerId}'` : ''}
`);
const { total } = recordsQuery.rows[0];
const totalPages = Math.ceil(total / limit);
const offsets = limit * (page - 1);
const query = { const query = {
text: `SELECT text: `SELECT
sales.id, invoice, date, amount, offices.name as office_name sales.id, invoice, date, amount, offices.name as office_name, users.name as casier
FROM sales FROM sales
LEFT JOIN offices ON offices.id = sales.office_id LEFT JOIN offices ON offices.id = sales.office_id
LEFT JOIN users ON users.id = sales.created_by
${customerId ? `LEFT JOIN customers ON customers.id = sales.customer_id` : ''}
WHERE WHERE
sales.office_id = (SELECT id FROM offices WHERE company_id = $1 LIMIT 1) sales.office_id = (SELECT id FROM offices WHERE company_id = $1 LIMIT 1)
${q ? `AND invoice ILIKE '%${q}%'` : ''}
${customerId ? `AND customer_id = '${customerId}'` : ''}
AND date::DATE BETWEEN $2 AND $3 AND date::DATE BETWEEN $2 AND $3
ORDER BY sales.created_at DESC`, ORDER BY sales.created_at DESC
values: [companyId, startDate, endDate], LIMIT $4 OFFSET $5
`,
values: [companyId, startDate, endDate, limit, offsets],
}; };
const results = await this._pool.query(query); const { rows } = await this._pool.query(query);
return results.rows; return {
sales: rows,
meta: {
page,
total,
totalPages,
},
};
} }
async getSaleById(saleId) { async getSaleById(saleId) {
@ -87,10 +117,14 @@ class SalesService {
const query = { const query = {
text: `SELECT text: `SELECT
date, invoice, sales.description, amount, discount, users.name as creator, offices.name as office_name date, invoice, sales.description, amount, discount,
users.name as casier,
offices.name as office_name,
customers.id as customer_id, customers.name as customer_name
FROM sales FROM sales
LEFT JOIN offices ON offices.id = sales.office_id LEFT JOIN offices ON offices.id = sales.office_id
LEFT JOIN users ON users.id = sales.created_by LEFT JOIN users ON users.id = sales.created_by
LEFT JOIN customers ON customers.id = sales.customer_id
WHERE sales.id = $1`, WHERE sales.id = $1`,
values: [saleId], values: [saleId],
}; };

@ -0,0 +1,13 @@
const PostCustomerPayloadSchema = require('./schema');
const InvariantError = require('../../exceptions/InvariantError');
const CustomerValidator = {
validatePostCustomerPayload: (payload) => {
const validationResult = PostCustomerPayloadSchema.validate(payload);
if (validationResult.error) {
throw new InvariantError(validationResult.error.message);
}
},
};
module.exports = CustomerValidator;

@ -0,0 +1,10 @@
const Joi = require('joi');
const PostCustomerPayloadSchema = Joi.object({
name: Joi.string().required(),
phone: Joi.string().allow(''),
address: Joi.string().allow(''),
description: Joi.string().allow(''),
});
module.exports = PostCustomerPayloadSchema;

@ -19,6 +19,8 @@ const PostPurchasePayloadSchema = Joi.object({
const GetPurchasesPayloadSchema = Joi.object({ const GetPurchasesPayloadSchema = Joi.object({
startDate: Joi.date().required(), startDate: Joi.date().required(),
endDate: Joi.date().required(), endDate: Joi.date().required(),
page: Joi.string().allow(''),
q: Joi.string().allow(''),
}); });
module.exports = { PostPurchasePayloadSchema, GetPurchasesPayloadSchema }; module.exports = { PostPurchasePayloadSchema, GetPurchasesPayloadSchema };

@ -2,6 +2,7 @@ const Joi = require('joi');
const PostSalePayloadSchema = Joi.object({ const PostSalePayloadSchema = Joi.object({
officeId: Joi.string().guid().required(), officeId: Joi.string().guid().required(),
customerId: Joi.string().guid().required(),
date: Joi.date().required(), date: Joi.date().required(),
invoice: Joi.string().required(), invoice: Joi.string().required(),
amount: Joi.number().required(), amount: Joi.number().required(),
@ -19,6 +20,9 @@ const PostSalePayloadSchema = Joi.object({
const GetSalesPayloadSchema = Joi.object({ const GetSalesPayloadSchema = Joi.object({
startDate: Joi.date().required(), startDate: Joi.date().required(),
endDate: Joi.date().required(), endDate: Joi.date().required(),
page: Joi.string().allow(''),
q: Joi.string().allow(''),
customerId: Joi.string().allow('').guid(),
}); });
module.exports = { PostSalePayloadSchema, GetSalesPayloadSchema }; module.exports = { PostSalePayloadSchema, GetSalesPayloadSchema };

Loading…
Cancel
Save