6

I'm writting a command line program which calculates the total price of an order, using info from a CSV file.

Data inside sample.catalog.csv:

P1,5,1000.00
P2,8,250.00
P3,15,125.00
P4,10,250.00
P5,2,2500.00

And the program must run from the command line with the following arguments:

Example: $ CalculateOrder sample.catalog.csv P1 2 P2 4

(P4 6 P10 5 P12 1 are products and quantity available from csv file)

Total: 4151,25

This is what I have at the moment:

var program = require('commander');
const csv = require('csv');
const fs = require('fs');


program
    .version('1.0.0')
    .option('-l, --list [list]', 'list of order prices in sample.catalog.csv')
    .parse(process.argv)

console.log("hello world")
console.log("list of order prices", program.list);


/* 
    To read csv file and print the data to the console:
    [node orderPrice --list input/sample.catalog.csv]
*/

let parse = csv.parse;
let stream = fs.createReadStream(program.list)
    .pipe(parse({ delimiter: ',' }));

var total = 0;
const vat = 23;
const totalWithVat = total * vat;

stream
.on('data', function (data) {
    let product = data[0];
    let quantity = data[1];
    let price = data[2];
    console.log(product, quantity, price);
    calculateOrder = () => {
        if (quantity > 20) {
            stream.destroy(new Error("Quantity exceeds stored amounts"));
        }
        total += price * quantity;
    }
})

.on("finish", function () {
    console.log("Total price:", totalWithVat);
})

.on("error", function (error) {
    console.error("The following error occured:", error);
})

I am having the following error:

λ node orderPrice calculateOrder sample.catalog.csv P1 2 P2 4
hello world
list of order prices undefined
fs.js:636
binding.open(pathModule._makeLong(path),
      ^

TypeError: path must be a string or Buffer
    at Object.fs.open (fs.js:636:11)
    at ReadStream.open (fs.js:1982:6)
    at new ReadStream (fs.js:1969:10)
    at Object.fs.createReadStream (fs.js:1923:10)
    at Object.<anonymous> (E:\order-price\orderPrice.js:31:17)
    at Module._compile (module.js:643:30)
    at Object.Module._extensions..js (module.js:654:10)
    at Module.load (module.js:556:32)
    at tryModuleLoad (module.js:499:12)
    at Function.Module._load (module.js:491:3)

I'm a Node.js newbie and any help is appreciated. Thank you.

6
  • What is the orderPrice you mentioned in the question? Commented Aug 4, 2018 at 16:20
  • orderPrice is my main file: orderPrice.js @eskawl Commented Aug 4, 2018 at 16:22
  • so you should be doing node orderPrice.js --list "P4 6 P10 5 P12 1" Commented Aug 4, 2018 at 16:27
  • λ node orderPrice.js --list P1 2 P2 4 hello world list of order prices P1 events.js:183 throw er; // Unhandled 'error' event ^ Error: ENOENT: no such file or directory, open 'E:\order-price\P1' @eskawl Commented Aug 4, 2018 at 16:29
  • Oh! I see you are trying to read a file. In that case node orderPrice.js --list Catalog.txt would work. Commented Aug 4, 2018 at 16:31

3 Answers 3

2

Change line

let stream = fs.createReadStream(program.list)

to

let stream = fs.createReadStream(program.argv[some number])

where some number is position at which you mention filename

e.g. run program with following command

node test.js somevar filename

then somenumber = 3

0th param > node
1st param > test.js (file to run)
2nd > somevar
3rd > filename

Another error:

Final code will look like

const csv = require('fast-csv');
const fs = require('fs');

console.log("hello world")
console.log("list of order prices", process.argv[2]);
let required_products=[]
for(var i=3;i<process.argv.length;){
   let temp=[]
   temp.name=process.argv[i++]
   temp.quantity=process.argv[i++]
   required_products.push(temp)
}
/*
    To read csv file and print the data to the console:
    [node orderPrice --list input/sample.catalog.csv]
*/

let stream = fs.createReadStream(process.argv[2]);

var total = 0;
var csvStream = csv()
    .on("data", function(data){
         let product_name = data[0];
         let quantity = data[1];
         let price = data[2];

         required_products.forEach(function(product){

             if(product['name']==product_name){
               if(parseInt(product['quantity'])>parseInt(quantity)){
                 console.log('Quantity required for product '+product['name']+' '+product['quantity']+' is greater than available '+quantity);
                 process.exit(1)
               }else{
                 total += parseInt(price) * parseInt(product['quantity']);
               }
             }
         })
    })
    .on("end", function(){
         console.log("done");
         let totalWithVat = total * (1+ 0.23);
         console.log("Total price:", totalWithVat);
    }).on("error", function (error) {
        console.error("The following error occured:", error);
    })
 stream.pipe(csvStream);
Sign up to request clarification or add additional context in comments.

6 Comments

Sorry, I didn't understand your explanation. Also, have you checked if it is calculating properly? @Shubham
check now if you can understand @RCohen
So, in my case is something like this? node orderPrice.js 3 sample.catalog.csv @Shubham
I am still a bit confused. I need to calculate the price and for the command node orderPrice -l sample.catalog.csv P1 2 P2 4 to run the calculation, I need your suggested code. Correct? @Shubham
why are you mentioning p1 2 p2 4 here ? it should be in csv file
|
1

It may sound glib, but program.list is undefined, which is why you can't read from it. It is undefined because you haven't set up commander to know how it maps from the command line. If you review examples in the commander documentation it might provide more light (and look at the help for "variadic arguments"). You can follow this example on how to use command and action methods.

I recommend if you are just starting, don't use packages like commander if you don't need to. Your question really is about using commander. This question provides some great hints as to how to get at command line arguments.

2 Comments

Okay, then why console.log("list of order prices", program.list); works, when I do node orderPrice --list sample.catalog.csv? @Micromuncher
It works because you've defined --list as an option, so it gets populated. In your example "node orderPrice calculateOrder sample.catalog.csv P1 2 P2 4" you haven't told commander how to process the arguments. As a kludge you could access the arguments directly without commander if list is undefined. Does that makes sense?
0

With the following directory structure:

- .. - orderPrices.js - sample.catalog.csv

You can execute node orderPrices.js --list sample.catalog.csv to make it work.

If your CSV file is located else where. You can you path module's path.resolve function to get the CSV file through its relative position in the following manner.

fs.createReadStream(path.resolve(__dirname, program.list)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.