diff --git a/controllers/DocumentController.js b/controllers/DocumentController.js new file mode 100644 index 0000000..e26797d --- /dev/null +++ b/controllers/DocumentController.js @@ -0,0 +1,99 @@ +import fs from 'fs'; +import Document from "../models/Document.js"; + +import checkValidationObjectId from '../libraries/checkValidationObjectId.js'; + +class DocumentController { + async index(req, res) { + try { + const documents = await Document.find(); + if(!documents) { throw { code: 404, message: "DOCUMENT_DATA_NOT_FOUND", data: null, status: false } } + + return res.status(200).json({ + status: true, + message: "LIST_DOCUMENT", + data: documents + }); + } catch (error) { + return res.status(error.code || 500).json({ + status: false, + message: error.message, + data: null + }); + } + } + + async store(req, res) { + try { + const { name, document_type } = req.body; + if(!name) { return { status: false, code: 428, message: "NAME_IS_REQUIRED" } } + if(!document_type) { return { status: false, code: 428, message: "TYPE_IS_REQUIRED" } } + + const data = new Document({ name: name, document_type: document_type }); + const document = await data.save(); + if(!document) { throw { code: 500, message: "Export File Gagal!", data: null, status: false } } + + return res.status(200).json({ + status: true, + message: "Export File Berhasil!", + data: document, + }) + } catch (error) { + return res.status(error.code || 500).json({ + status: false, + message: error.message, + data: null + }); + } + } + + async destroy(req, res) { + try { + const {id} = req.params + if(!id) { throw { code: 420, message: "ID_REQUIRED", data: null, status: false } } + + const checkObjId = await checkValidationObjectId(id, Document, "DOCUMENT", true) + if(!checkObjId.status) return res.status(checkObjId.code).json({ + status: false, + message: checkObjId.message, + data: null + }); + + const document = await Document.findOneAndDelete({ _id: id }) + if(!document) { throw { code: 500, message: "Gagal menghapus file!", data: null, status: false } } + + const filepath = `exports/${checkObjId.data.name}`; + + fs.stat('foo.txt', function(err, stat) { + if (err == null) { + fs.unlink(filepath, (err) => { + if(err) { + console.log(err) + return res.status(500).json({ + status: false, + message: "Gagal menghapus file pada server!", + data: null + }); + } + }) + } else { + console.log('Some other error: ', err.code); + } + }); + + return res.status(200).json({ + status: true, + message: "Berhasil menghapus file!", + data: document, + }) + } catch (error) { + return res.status(error.code || 500).json({ + status: false, + message: error.message, + data: null + }); + } + } +} + +export default new DocumentController; \ No newline at end of file diff --git a/controllers/PDFController.js b/controllers/PDFController.js new file mode 100644 index 0000000..0d5e451 --- /dev/null +++ b/controllers/PDFController.js @@ -0,0 +1,41 @@ +import Document from "../models/Document.js"; +import TransactionLine from "../models/TransactionLine.js"; + +import TransactionLineService from '../services/TransactionLineService.js'; + +import { fDate } from '../libraries/formatTime.js'; + +class PDFController { + async export(req, res) { + try { + const { startDate, endDate } = req.query; + + const query = await TransactionLineService.generateQuerySearch(req); + if(!query.status) throw { code: query.code, message: "ERROR_QUERY_SEARCH", data: null, status: false } + + let result = TransactionLine.aggregate(query.aggregate); + + const lines = await result; + + const filename = `${fDate(startDate*1)}-${fDate(endDate*1)}.pdf` + // writeFileSync(`exports/${filename}`, pdf); + + const data = new Document({ name: filename, document_type: 'pdf' }); + const document = await data.save(); + + if(!document) { throw { code: 500, message: "Export File Gagal!", data: null, status: false } } + return res.status(200).json({ + status: true, + message: "SUCCESS_EXPORT", + }); + } catch (error) { + if(!error.code) { error.code = 500 } + return res.status(error.code).json({ + status: false, + message: error.message, + }); + } + } +} + +export default new PDFController; \ No newline at end of file diff --git a/controllers/TransactionLineController.js b/controllers/TransactionLineController.js index 654b9dc..42e2b3d 100644 --- a/controllers/TransactionLineController.js +++ b/controllers/TransactionLineController.js @@ -13,8 +13,6 @@ class TransactionController { if(!query.status) throw { code: query.code, message: "Query Pencarian Eror!", data: null, status: false } let result = TransactionLine.aggregate(query.aggregate); - console.log(query.aggregate); - const lines = await result; const total = await TransactionLine.countDocuments(query.aggregate.at(-1)['$match']); diff --git a/controllers/VendorController.js b/controllers/VendorController.js index e278200..fc7042f 100644 --- a/controllers/VendorController.js +++ b/controllers/VendorController.js @@ -113,8 +113,8 @@ class VendorController { data: null }); - // check if account has transaction - const vendors = await TransactionLine.find({ accountId: id }); + // check if vendor has transaction + const vendors = await TransactionLine.find({ vendorId: id }); if(vendors.length > 0) { return res.status(500).json({ status: false, diff --git a/controllers/XlsxController.js b/controllers/XlsxController.js index d4f3677..81788dc 100644 --- a/controllers/XlsxController.js +++ b/controllers/XlsxController.js @@ -1,6 +1,7 @@ import { writeFileSync } from "node:fs"; import { Workbook } from "xlsx-kaku"; +import Document from "../models/Document.js"; import TransactionLine from "../models/TransactionLine.js"; import TransactionLineService from '../services/TransactionLineService.js'; @@ -10,7 +11,6 @@ import { fDate } from '../libraries/formatTime.js'; class XlsxController { async export(req, res) { try { - console.log(req.query) const query = await TransactionLineService.generateQuerySearch(req); if(!query.status) throw { code: query.code, message: "ERROR_QUERY_SEARCH", data: null, status: false } let result = TransactionLine.aggregate(query.aggregate); @@ -19,17 +19,20 @@ class XlsxController { const wb = new Workbook(); const ws = wb.addWorksheet("TRANSAKSI"); + const { startDate, endDate } = req.query; ws.setCell(0, 0, { type: "string", value: "DAFTAR TRANSAKSI", style: { alignment: {horizontal: "center", vertical: "center"} } }); ws.setMergeCell({ ref: "A1:F2" }); ws.setCell(2, 0, { type: "string", value: `${fDate(startDate*1)} sampai ${fDate(endDate*1)}`, style: { alignment: {horizontal: "center", vertical: "center"} } }); ws.setMergeCell({ ref: "A3:F3" }); + ws.setMergeCell({ ref: "A4:F6" }); let row = 3 let currentDate = ''; let number = 0; let income = 0; let expense = 0; + let margin = 0; lines.map((line) => { if(currentDate !== fDate(line.date)) { if(row !== 3) { @@ -38,11 +41,19 @@ class XlsxController { ws.setMergeCell({ ref: `A${row+1}:D${row+1}` }) ws.setCell(row, 4, { type: "number", value: income, style: { alignment: {horizontal: "right", vertical: "center"} } }); ws.setCell(row, 5, { type: "number", value: expense, style: { alignment: {horizontal: "right", vertical: "center"} } }); + + margin = income-expense; + row += 1; + ws.setCell(row, 0, { type: "string", value: "Margin" }); + ws.setMergeCell({ ref: `A${row+1}:D${row+1}` }); + ws.setCell(row, 4, { type: "number", value: margin, style: { alignment: {horizontal: "right", vertical: "center"} } }); + ws.setMergeCell({ ref: `E${row+1}:F${row+1}` }); } number = 0; income = 0; expense = 0; row += 3; + ws.setMergeCell({ ref: `A${row-1}:F${row}` }) currentDate = fDate(line.date); ws.setCell(row, 0, { type: "string", value: `${fDate(line.date*1)}`, style: { alignment: {horizontal: "center", vertical: "center"} } }); @@ -75,9 +86,22 @@ class XlsxController { ws.setMergeCell({ ref: `A${row+1}:D${row+1}` }) ws.setCell(row, 4, { type: "number", value: income, style: { alignment: {horizontal: "right", vertical: "center"} } }); ws.setCell(row, 5, { type: "number", value: expense, style: { alignment: {horizontal: "right", vertical: "center"} } }); + + margin = income-expense; + row += 1; + ws.setCell(row, 0, { type: "string", value: "Margin" }); + ws.setMergeCell({ ref: `A${row+1}:D${row+1}` }); + ws.setCell(row, 4, { type: "number", value: margin, style: { alignment: {horizontal: "right", vertical: "center"} } }); + ws.setMergeCell({ ref: `E${row+1}:F${row+1}` }); const xlsx = wb.generateXlsxSync(); - writeFileSync(`${fDate(startDate*1)}-${fDate(endDate*1)}.xlsx`, xlsx); + const filename = `${fDate(startDate*1)}-${fDate(endDate*1)}.xlsx` + writeFileSync(`exports/${filename}`, xlsx); + + const data = new Document({ name: filename, document_type: 'excel' }); + const document = await data.save(); + + if(!document) { throw { code: 500, message: "Export File Gagal!", data: null, status: false } } return res.status(200).json({ status: true, diff --git a/exports/01 Jul 2024-28 Jul 2024.xlsx b/exports/01 Jul 2024-28 Jul 2024.xlsx deleted file mode 100644 index 692bae5..0000000 Binary files a/exports/01 Jul 2024-28 Jul 2024.xlsx and /dev/null differ diff --git a/models/Document.js b/models/Document.js index 883be7d..8585cc5 100644 --- a/models/Document.js +++ b/models/Document.js @@ -1,7 +1,7 @@ import mongoose from "mongoose"; const DocumentSchema = new mongoose.Schema({ - label: { type: String, required: true }, + name: { type: String, required: true }, document_type: { type: String, enum: [ diff --git a/routes/index.js b/routes/index.js index 6e57bf9..4000701 100644 --- a/routes/index.js +++ b/routes/index.js @@ -3,6 +3,8 @@ import express from "express"; // controllers import AccountController from '../controllers/AccountController.js'; import AuthController from '../controllers/AuthController.js'; +import DocumentController from '../controllers/DocumentController.js'; +import PDFController from '../controllers/PDFController.js'; import TransactionController from '../controllers/TransactionController.js'; import TransactionLineController from '../controllers/TransactionLineController.js'; import UserController from '../controllers/UserController.js'; @@ -51,8 +53,13 @@ router.post('/vendors', auth(), VendorController.store); router.get('/vendors/:id', auth(), VendorController.show); router.put('/vendors/:id', auth(), VendorController.update); router.delete('/vendors/:id', auth(), VendorController.destroy); +// file +router.get('/documents', DocumentController.index); +router.post('/documents', auth(), DocumentController.store); +router.delete('/documents/:id', auth(), DocumentController.destroy); // export router.get('/transactions/export/xlsx', auth(), XlsxController.export); +router.get('/transactions/export/pdf', auth(), PDFController.export); // server router.get('/', function(req, res) {