代码之家  ›  专栏  ›  技术社区  ›  NVO

异步中的多个保存操作。forEachOf公司

  •  0
  • NVO  · 技术社区  · 7 年前

    我在mongo集合中循环了一些付款。payoutdate==today()的所有付款必须导出并写入sepa文件,以便我们可以通过银行处理付款。

    付款在创建时没有发票号,我们在处理付款时生成一个发票号(通过上述函数导出)。 问题是,当我们运行要导出多个付款的函数时,所有付款都得到相同的发票号。所以看起来,在处理下一笔付款之前,最后一次保存操作没有完成。

    const fs = require('fs');
    const async = require('async');
    const DateDiff = require('date-diff');
    const SEPA = require('sepa');
    const shopService = require(path.join(__dirname, '..', 'services', 'shop.service'));
    
        async.forEachOf(payments, function(payment, key, paymentDone){            
            var diff = new DateDiff(new Date(payment.payoutDate), new Date());
            if(payment.payoutDate && payment.amount > 0 && payment.completed == false && payment.exported == false && diff.days() <= 0){
                //payment has amount, is not completed and is not exported, create an SEPA transfer, and set the payment to completed
                //but first create an invoicenumber
    
                    orderService.updateOrderPayment(payment.orderId, {generateInvoiceNumber: true}, function(err, result){
                        if(err){
                            console.log("error updating payment", err);
                        }
                        //reget the payment to avoid duplicated invoice numbers
    
                        orderService.getPayment(result.orderId, function(err, payment){
                            if(err){
                                console.log("error getting payment", err);
                            }
    
                            Shop.findOne({_id: payment.shopId}).exec(function(err, shop){
                                if(shop && shop.bankAccountNumber && shop.accountHolder && shop.bicCode){
                                   //create transaction and add this to the file
                                }else{
                                    var result = {
                                        paymentID: payment._id,
                                        orderId: payment.orderId,
                                        status: payment.status,
                                        message: "shop does not have an iban, accountholder or biccode",
                                        shop: shop.nameSlug
                                    }
                                    resultArray.push(result);
                                    console.log("shop does not have an iban, accountholder or biccode", shop.nameSlug);
                                    paymentDone();
                                }
    
                                orderService.updateOrderPayment(payment.orderId, {status: 'completed'}, function(err, result){
                                    orderService.updateOrderStatusById(payment.orderId, {status: 'Granted', date: new Date(), comment: null});
                                    var result = {
                                        paymentID: payment._id,
                                        orderId: payment.orderId,
                                        status: payment.status,
                                        message: "payment exported",
                                    }
                                    resultArray.push(result);
                                    counter++;
                                    paymentDone();
                                })
                            })
                        })    
                    })    
            }else{
                var result = {
                    paymentID: payment._id,
                    orderId: payment.orderId,
                    status: payment.status,
                    message: "order already processed"
                }
                resultArray.push(result);
                paymentDone();
            }
        }, function(){
            if(resultArray.length == payments.length){
                //console.log("Result", resultArray);
                if(counter == 0){
                    res.status(200).json({"message":"No orders to export", resultArray});
                }else{
                    res.set({"Content-Disposition":"attachment; filename=\"sepa.xml\""});
                    res.send(doc.toString());
                }
            }
        })
    

    function updateOrderPayment(orderId, paymentStatus, callback){
        console.log("updateOrderPayment");
        if(!paymentStatus){
            return callback("No payment details provided");
        }else{
            if(!paymentStatus.comment){
                paymentStatus.comment = null;
            }
        }
        getPayment(orderId, function(err, payment){
            if(err)
                return callback(err);
    
            handlePayment(payment, paymentStatus, function(result){
                result.save(function(err, result){
                    if(err){
                        return callback(err);
                    }
                    console.log("payment saved");
                    return callback(null, result);
                })
            })
        })
    }
    
    function handlePayment(payment, paymentStatus, callback){
        if(paymentStatus.status){
            var status = {
                status: paymentStatus.status,
                comment: paymentStatus.comment,
                date: Date.now()
            }
            payment.status.push(status);
        }
    
        if(paymentStatus.generateInvoiceNumber){
            console.log("generateInvoiceNumber");
            var invoiceNumber =0;
    
            Payment.findOne({invoiceNumber: {$exists:true}}).sort({_id: -1}).exec(function(err, latestPaymentsWithNumber){
    
                if(latestPaymentsWithNumber && latestPaymentsWithNumber.invoiceNumber){
                    invoiceNumber = latestPaymentsWithNumber.invoiceNumber.split("-")[1];
                }
    
                var date = new Date();
                payment.invoiceNumber = date.getFullYear().toString() + date.getMonth().toString() + "-" + (parseInt(invoiceNumber)+1);
                console.log("number", payment.invoiceNumber);
                return callback(payment);
            })
        }
    
        if(paymentStatus.status == 'returned' || paymentStatus.status == 'cancelled'){
            payment.cancelled = true;
            payment.amount = 0;
            payment.payoutDate = null;
            return callback(payment);
        }
    
        if(paymentStatus.status == 'completed'){
            payment.completed = true;
            payment.exported = true;
            payment.payoutDate = null;  
            return callback(payment);
        }
    }
    
    function getPayment(orderId, callback){
        Payment.findOne({orderId: orderId}).exec(function(err, payment){
            if(err){
                return callback(err);
            }
            return callback(null, payment);
        })
    }
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   aug2uag    7 年前

    您有两个选择:

    1) 在范围内实现对save操作的回调

    x.forEach(function(_x) {
      _x.save(function(err) { });
    });
    

    function async(x, cb) {
      x.operations(cb)
    }
    
    function series(x) {
      if (x) {
        async(x, function() { series(xs.pop()); });
      } else // finished
    }
    
    series(xs.pop()); // xs is the array you're iterating
    
        2
  •  0
  •   NVO    7 年前

    我已更改查询以查找最后一个 invoiceNumber

    Payment.find({invoiceNumber: {$ne:null}}).sort({date: -1}).limit(1).exec(function(err, latestPaymentsWithNumber){
    

    payments : async.eachSeries(payments, function(payment, paymentDone) {

    我做了一个结果。保存在第一次回调到asume我有正确的数据

    result.save(function(err, payment){