gaber-elsayed

bill pdf

Mar 6th, 2021
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.24 KB | None | 0 0
  1. //////bill.js
  2.  
  3. /*global console require module*/
  4. 'use strict';
  5.  
  6. var express = require('express');
  7. var router = express.Router();
  8. var pdf = require('html-pdf');
  9. var cheerio = require('cheerio');
  10. var randomstring = require('randomstring');
  11. var debug = require('debug')('Foodbox-HQ:server');
  12. var format = require('string-format');
  13. var path = require('path')
  14.  
  15. format.extend(String.prototype);
  16. var config = require('../models/config');
  17. var conString = config.dbConn;
  18.  
  19. // Handlers for bill related code
  20.  
  21. // This returns the bill pdf given the file name
  22. router.get('/:id', function(req, res, next) {
  23. // XXX: Its better to group the files according to day/month than to
  24. // keep them in a single folder
  25. var bill_file_code = req.params.id;
  26. var filePath = process.env.BILL_FOLDER;
  27. filePath = path.join(filePath, 'bill-' + bill_file_code + '.pdf');
  28. res.sendFile(filePath);
  29. });
  30.  
  31. // This creates a pdf file from the given html and stores it.
  32. router.post('/', function(req, res, next) {
  33. // getting the bill html
  34. var bill_text = req.body.bill_text;
  35. // parsing it into cheerio struct
  36. var $ = cheerio.load(bill_text);
  37. // Filling the images in the html
  38. var filePath = path.join(__dirname, '/../');
  39. filePath = path.join(filePath, 'public/img/email.png');
  40. $("#mail img").attr("src", 'file://' + filePath);
  41.  
  42. filePath = path.join(__dirname, '/../');
  43. filePath = path.join(filePath, 'public/img/fb.png');
  44. $("#fb img").attr("src", 'file://' + filePath);
  45.  
  46. filePath = path.join(__dirname, '/../');
  47. filePath = path.join(filePath, 'public/img/twitter.png');
  48. $("#twitter img").attr("src", 'file://' + filePath);
  49.  
  50. var rand_string = randomstring.generate(5);
  51. var bill_file = 'bill-' + rand_string + '.pdf';
  52. var bill_folder = process.env.BILL_FOLDER;
  53. var options = { filename: path.join(bill_folder, bill_file), format: 'Letter' };
  54. debug('Bill location- ' + options.filename);
  55. // converting the pdf file to a buffer and passing it along to the print function
  56. pdf.create($.html(), options).toFile(function(err, buffer) {
  57. if (err) return console.error(err);
  58. debug('Bill {} successfully generated'.format(options.filename));
  59. res.send({"bill_location": "/bill/"+rand_string});
  60. });
  61. });
  62.  
  63. module.exports = router;
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71. //////bill_generator_utils.js
  72.  
  73.  
  74.  
  75. /* global require __dirname module console */
  76. 'use strict';
  77.  
  78. var _ = require('underscore');
  79. var pg = require('pg');
  80. var async = require('async');
  81. var format = require('string-format');
  82. var moment = require('moment');
  83. var jsreport = require('jsreport');
  84. var path = require('path');
  85. var fs = require('fs');
  86. var dbUtils = require('../models/dbUtils')
  87.  
  88. format.extend(String.prototype);
  89. var config = require('../models/config');
  90. var conString = config.dbConn;
  91.  
  92. var prepare_and_store_bill_data = function(bill_date, outlet_id, callback) {
  93. debugger;
  94. pg.connect(conString, function(err, client, done) {
  95. if (err) {
  96. callback(err, null);
  97. return;
  98. }
  99. // Aggregate all bills
  100. var query_text =
  101. "SELECT \
  102. (select bill_no from bill_items where sales_order_id= so.id limit 1) as bill_no, \
  103. soi.sales_order_id as so_id, \
  104. soi.food_item_id as item_id, \
  105. coalesce(bi.quantity, soi.quantity) as qty, \
  106. so.outlet_id as outlet_id, \
  107. so.time as time, \
  108. soi.quantity as refund_qty, \
  109. r.id as fv_id, \
  110. r.name as fv_name, \
  111. r.address as fv_address, \
  112. r.phone_no as fv_phone, \
  113. r.st_no fv_st_no, \
  114. r.tin_no as fv_tin_no, \
  115. fi.name as item_name, \
  116. fi.mrp as mrp, \
  117. fi.selling_price as selling_price, \
  118. fi.service_tax_percent as st_perc, \
  119. fi.vat_percent as vat_perc, \
  120. fi.foodbox_fee as foodbox_fee, \
  121. fi.restaurant_fee as restaurant_fee, \
  122. fi.side_order as side_order_name, \
  123. o.start_of_day as start_of_day, \
  124. o.end_of_day as end_of_day, \
  125. o.is24hr as is24hr, \
  126. o.abatement_percent as abatement_perc, \
  127. r.gstin_no as gstin_no, \
  128. fi.sgst_percent as sgst_perc ,\
  129. fi.cgst_percent as cgst_perc, \
  130. r.entity_name as entity \
  131. FROM \
  132. sales_order_items soi FULL OUTER JOIN \
  133. bill_items as bi ON bi.sales_order_id = soi.sales_order_id and bi.food_item_id = soi.food_item_id, \
  134. sales_order as so, \
  135. restaurant as r, \
  136. food_item as fi, \
  137. outlet as o \
  138. WHERE \
  139. DATE(so.time) >= $1 \
  140. AND \
  141. o.id = $2 \
  142. AND \
  143. so.outlet_id = o.id \
  144. AND \
  145. soi.sales_order_id = so.id \
  146. AND \
  147. coalesce(soi.food_item_id, bi.food_item_id) = fi.id \
  148. AND \
  149. r.id = fi.restaurant_id \
  150. ORDER BY bill_no asc";
  151.  
  152. var query_params = [bill_date, outlet_id];
  153.  
  154. client.query(query_text, query_params,
  155. function(query_err, query_res) {
  156. if(query_err) {
  157. done(client);
  158. callback(query_err, null);
  159. return;
  160. } else {
  161. debugger;
  162. var msg = 'Purchase Orders were issued on this day, but no Sales were made, so there are no bills to display.';
  163. done();
  164. var bills = query_res.rows;
  165. if(bills.length == 0) {
  166. callback(msg, null);
  167. return;
  168. }
  169. var first = _.first(bills);
  170. var filteredBills = [];
  171. if(first.is24hr) {
  172. filteredBills = _.filter(bills, function(b) {
  173. return (moment(b.time).format('YYYY-MM-DD') == bill_date);
  174. });
  175. } else {
  176. var last_eod,next_eod = null;
  177. if(first.start_of_day < first.end_of_day) {
  178. var prev_day = moment(bill_date).add(-1, 'days').format('YYYY-MM-DD');
  179. last_eod = moment(prev_day + ' ' + first.end_of_day);
  180. next_eod = moment(bill_date + ' ' + first.end_of_day).add(1, 'hours');
  181. } else {
  182. var next_day = moment(bill_date).add(1, 'days').format('YYYY-MM-DD');
  183. last_eod = moment(bill_date + ' ' + first.end_of_day);
  184. next_eod = moment(next_day + ' ' + first.end_of_day).add(1, 'hours');
  185. }
  186.  
  187. filteredBills = _.filter(bills, function(b) {
  188. return moment(b.time).isBetween(last_eod, next_eod);
  189. });
  190. }
  191. if(filteredBills.length == 0) {
  192. callback(msg, null);
  193. return;
  194. }
  195. dbUtils.store_daily_bill(bill_date, outlet_id, filteredBills, callback);
  196. return;
  197. }
  198. });
  199. });
  200. };
  201.  
  202. var fetch_bill_data = function(bill_date, outlet_id, fv_id, callback) {
  203. dbUtils.getArchivedBillData(outlet_id, bill_date, function(err, res){
  204. debugger;
  205. var msg = 'Purchase Orders were issued on this day, but no Sales were made, so there are no bills to display.';
  206. if(err){
  207. callback(msg, null);
  208. return;
  209. }
  210. var consolidated_bills = res;
  211. if (fv_id) {
  212. // filter result by fv.
  213. consolidated_bills = _.filter(res, function(row){
  214. return (row.fv_id == fv_id);
  215. });
  216. }
  217.  
  218. if(_.isEmpty(consolidated_bills)) {
  219. callback(msg, null);
  220. return;
  221. }
  222. callback(null, consolidated_bills);
  223. return;
  224. });
  225. };
  226. var gst_date='2017-07-01';
  227. var get_bill_bundle = function(bill_data, callback) {
  228. debugger;
  229. // Group bills by order id and food item id.
  230. var grouped_bills = [];
  231. var grouped = _.groupBy(bill_data, function(v) {
  232. return v.so_id + "#" + v.item_id;
  233. });
  234. _.each(_.keys(grouped), function(key){
  235. var bill = {};
  236. var orders = grouped[key];
  237. var sample = _.first(orders);
  238.  
  239. bill["bill_no"] = sample.bill_no;
  240. bill["so_id"] = sample.so_id;
  241. bill["time"] = moment(sample.time);
  242. bill["qty"] = sample.qty;
  243. var refunds = _.filter(orders, function(o){
  244. return (o.refund_qty && (o.refund_qty < 0));
  245. });
  246. bill["refund_qty"] = _.reduce(refunds, function(memo, o){
  247. return memo + o.refund_qty;
  248. }, 0);
  249.  
  250. bill["item_id"] = sample.item_id;
  251. bill["item_name"] = sample.item_name;
  252. bill["fv_id"] = sample.fv_id;
  253. bill["fv_name"] = sample.fv_name;
  254. bill["fv_address"] = sample.fv_address;
  255. bill["fv_phone"] = sample.fv_phone;
  256. bill["fv_st_no"] = sample.fv_st_no;
  257. bill["fv_tin_no"] = sample.fv_tin_no;
  258. bill["side_order_name"] = sample.side_order_name;
  259. bill["mrp"] = sample.mrp;
  260. bill["selling_price"] = sample.selling_price;
  261. bill["st_perc"] = sample.st_perc;
  262. bill["vat_perc"] = sample.vat_perc;
  263. bill["foodbox_fee"] = sample.foodbox_fee;
  264. bill["restaurant_fee"] = sample.restaurant_fee;
  265. bill["abatement_perc"] = sample.abatement_perc;
  266. bill["outlet_id"]=sample.outlet_id;
  267. // GST Changes
  268. //console.log("moment(sample.time,'YYYY-MM-dd')");
  269. //console.log(moment(sample.time,'YYYY-MM-dd'));
  270. if ( moment(sample.time).format('YYYY-MM-DD')>= gst_date){
  271. // console.log("INSIDE GST moment(sample.time,'YYYY-MM-dd')");
  272. // bill["sgst_perc"] = 9;//sample.vat_perc;
  273. // bill["cgst_perc"] = 9;//sample.vat_perc;
  274. // bill["gstin_no"] = "123456789ABCXYZ";
  275. // bill["entity"]=sample.fv_name;
  276. bill["sgst_perc"] = sample.sgst_perc;
  277. bill["cgst_perc"] = sample.cgst_perc;
  278. bill["gstin_no"] =sample.gstin_no ;
  279. bill["entity"]=sample.entity;
  280. }
  281.  
  282. grouped_bills.push(bill);
  283. });
  284.  
  285. // aggregate by bill no.
  286. var bills = [];
  287. var grouped = _.groupBy(grouped_bills, "bill_no");
  288. _.each(_.keys(grouped), function(bill_no) {
  289. var entries = grouped[bill_no];
  290. var fv_grouped = _.groupBy(entries, "fv_id");
  291. _.each(_.keys(fv_grouped), function(fv_id) {
  292. var bill = {};
  293. var first = fv_grouped[fv_id][0];
  294. bill["bill_no"] = bill_no;
  295. bill["fv_name"] = first["fv_name"];
  296. bill["fv_address"] = first["fv_address"] + " Ph:" + first["fv_phone"];
  297. bill["bill_date"] = moment(first["time"]).format('DD/MM/YYYY');
  298. bill["bill_time"] = moment(first["time"]).format('HH:mm:ss');
  299. bill["tin_no"] = first["fv_tin_no"];
  300. bill["st_no"] = first["fv_st_no"];
  301. bill["items"] = _.map(fv_grouped[fv_id], function(item) {
  302. var amount = Number(item.qty + item.refund_qty)*Number(item.selling_price);
  303. var mrp = Number(item.qty + item.refund_qty)*Number(item.mrp);
  304. var vat = Number(amount*item.vat_perc/100.0);
  305. //Gst changes
  306. var gst=0
  307. var ratePerItem=0;
  308. if (moment(first.time).format('YYYY-MM-DD') >=gst_date )
  309. {
  310. var gst_perc=first["sgst_perc"]+first["cgst_perc"];
  311.  
  312. gst =Number(amount*gst_perc/100.0);
  313. console.log("gst:"+gst);
  314. ratePerItem=((item.mrp/item.qty)*100)/(100+gst_perc);
  315. console.log("gratePerItemratePerItemst:"+ratePerItem);
  316. }
  317. if(item.vat_perc<5){
  318. amount+=vat;
  319. vat=0;
  320. }
  321. var st = mrp - amount - vat;
  322. return {
  323. name: item.item_name,
  324. qty: item.qty,
  325. refunds: item.refund_qty,
  326. amt: amount,
  327. display_amount: (amount.toFixed(2)),
  328. vat: vat,
  329. st: st,
  330. mrp: mrp,
  331. gst:gst,
  332. gst_perc:gst_perc,
  333. ratePerItem:Number(ratePerItem.toFixed(2)) //gst changes
  334. };
  335. });
  336. debugger;
  337. bill["vat_percent"] = (first.vat_perc).toFixed(2);
  338. bill["st_percent"] = (first.st_perc*first.abatement_perc/100).toFixed(2);
  339. //gst changes
  340.  
  341. if ( first.vat_perc <5){ // value is harcoded
  342. bill["display_vat"]=false;
  343. }
  344. else{
  345. bill["display_vat"]=true;
  346. }
  347.  
  348. bill["total"] = _.reduce(bill["items"],
  349. function(memo, it) { return memo + it.amt;}, 0).toFixed(2);
  350.  
  351. bill["vat"] = _.reduce(bill.items, function(memo, it){
  352. return memo + it.vat;
  353. }, 0).toFixed(2);
  354.  
  355. bill["st"] = _.reduce(bill.items, function(memo, it){
  356. return memo + it.st;
  357. }, 0).toFixed(2);
  358. console.log("first.time:"+first.time);
  359. if ( moment(first.time).format('YYYY-MM-DD')>= gst_date){
  360. bill["sgst_perc"] = (first.sgst_perc);
  361. bill["cgst_perc"] = (first.cgst_perc);
  362. bill["gst"] = _.reduce(bill.items, function(memo, it){
  363. return memo + it.gst;
  364. }, 0).toFixed(2);
  365. bill["cgst_amount"]=((bill["gst"]/(bill["sgst_perc"]+bill["cgst_perc"])) *bill["cgst_perc"]).toFixed(2);
  366. console.log("cgst amount:"+bill["cgst_amount"]);
  367. bill["sgst_amount"]=((bill["gst"]/(bill["sgst_perc"]+bill["cgst_perc"])) *bill["sgst_perc"]).toFixed(2);
  368. bill["fv_id"]=first.fv_id;
  369. bill["outlet_id"]=first.outlet_id;
  370. bill["entity"]=first.entity;
  371. bill["gstin_no"]=first.gstin_no;
  372. // console.log("outletid:"+ JSON.stringify( first));
  373. }
  374.  
  375. bill["grand_total"] = _.reduce(bill.items, function(memo, it){
  376. return memo + it.mrp;
  377. }, 0).toFixed(2);
  378.  
  379. bills.push(bill);
  380. });
  381. });
  382. callback(null, bills);
  383. return;
  384. };
  385.  
  386. var generate_bill_bundle_pdf = function(bills, callback) {
  387. var template_path = path.join(__dirname, '/../');
  388. template_path = path.join(template_path, 'public/reports/bill_bundle.html');
  389. var content = fs.readFileSync(template_path, 'utf8');
  390. jsreport.render({
  391. template: {
  392. content: content,
  393. engine: 'jsrender'
  394. },
  395. recipe: 'phantom-pdf',
  396. data: {
  397. bills: bills
  398. },
  399. }).then(function(out) {
  400. callback(null, out);
  401. }).catch(function(err) {
  402. callback(err, null);
  403. return;
  404. });
  405. };
  406.  
  407. var generate_bill_bundle_pdf_Gst = function(bills, callback) {
  408. var template_path = path.join(__dirname, '/../');
  409. template_path = path.join(template_path, 'public/reports/bill_bundle_Gst.html');
  410. var content = fs.readFileSync(template_path, 'utf8');
  411. jsreport.render({
  412. template: {
  413. content: content,
  414. engine: 'jsrender'
  415. },
  416. recipe: 'phantom-pdf',
  417. data: {
  418. bills: bills
  419. },
  420. }).then(function(out) {
  421. callback(null, out);
  422. }).catch(function(err) {
  423. callback(err, null);
  424. return;
  425. });
  426. };
  427.  
  428. module.exports = {
  429. prepare_and_store_bill_data: prepare_and_store_bill_data,
  430. fetch_bill_data: fetch_bill_data,
  431. get_bill_bundle: get_bill_bundle,
  432. generate_bill_bundle_pdf: generate_bill_bundle_pdf,
  433. generate_bill_bundle_pdf_Gst: generate_bill_bundle_pdf_Gst
  434. };
Add Comment
Please, Sign In to add comment