简体   繁体   中英

How should I calculate total sales from multiple tables in a IndexedDB database?

I'm trying to create a simple stock/sales application in JavaScript using Dexie.js. I'm not sure how to go about returning the Total Sales amount without writing awful recursive code that runs a query multiple times for just one product's total sales amount.

My schema is somewhat like this:

clients: "++id, name, phone",
order: "++id, clientId, daate",
order_content: "orderId, productId, qty",
product: "++id, name, mu, mk_cost, sa_cost, prod_cost",
stock: "++id, date, productId, qty, lot"

I store the product types in "Product" with prices and other details. When a order is placed I store the clientId in Order, then I use "order_content" to store the items there, using the orderId as a key to sort.

I basically want to do a total for every item and the sum that up.

I tried running the code below in a db.product.each() loop, but it seems like I'm complicating myself.

var product1Total = 0;
function calculateTotal(productId, price){
db.order_content
.where("productID")
.equals(productId)
.each(function(item){
product1Total += (price * qty)
})
}

Thank you!

If your goal is to get the total price for a specific order in a single query, and prod_cost is the cost of your product, and you want the total for a certain order, you should do it something like the following:

function calculateTotal (orderId) {
    return db.order_content
        .where('orderId').equals(orderId).toArray()
    .then(orderContents => {
        return Promise.all(
            orderContents.map(oc => db.product.get(oc.productId))
        ).then (products => {
            return orderContents.reduce (
                (total, oc, i) => total + oc.qty * producs[i].prod_cost, 0);
        });
    });
}

Or with async functions:

async function calculateTotal (orderId) {
    let orderContents = await db.order_content
        .where('orderId').equals(orderId).toArray();

    let products = await Promise.all(orderContents.map(oc =>
        db.product.get(oc.productId));

    return orderContents.reduce (
        (total, oc, i) => total + oc.qty * producs[i].prod_cost, 0);
}

Or with vanilla ES5 javascript:

function calculateTotal (orderId) {
    return db.order_content
        .where('orderId').equals(orderId).toArray()
    .then(function (orderContents) {
        return Dexie.Promise.all(
            orderContents.map(function (oc) {
                return db.product.get(oc.productId);
            })
        ).then (function (products) {
            return orderContents.reduce (
                function (total, oc, i) {
                    return total + oc.qty * producs[i].prod_cost;
                }, 0);
        });
    });
}

There's nothing wrong with your query, but you should encapsulate it in a promise-returning function. This is easy to accomplish by chaining the promise returned from Dexie's Collection.each().

function calculateTotal(productId, price) {
    var total = 0;
    return db.order_content
        .where("productID")
        .equals(productId)
        .each(function(item){
            total += (price * item.qty)
        }).then (function () {
            return total;
        });
}

Or in ES7:

async function calculateTotal (productId, price) {
    var total = 0;

    await db.order_content
        .where("productID")
        .equals(productId)
        .each (item => total += (price * item.qty));

    return total;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM