@builton/core-sdk
Version:
Builton JavaScript SDK.
143 lines (118 loc) • 4.25 kB
JavaScript
const store = require('store2');
const Orders = require('../collection/resources/orders');
const Order = require('../collection/objects/order');
const Payments = require('../collection/resources/payments');
class Cart {
constructor(request) {
this._cart = store.get('cart') || [];
this.request = request;
}
_findProductIndex(productId) {
return this._cart.findIndex((cartItem) => cartItem.productId === productId);
}
// Cart is valid if all item contain at least productId and quantity
_isCartValid() {
return !this._cart.some((item) => (!item.productId || !item.quantity));
}
_saveCart() {
store.set('cart', this._cart);
}
// Check to see if two subproduct lists contain the same items. Doesn't care about order
static _compareSubproducts(listA = [], listB = []) {
if (!listA.length && !listB.length) return true;
return listA.slice(0).sort().join('-') === listB.slice(0).sort().join('-');
}
set(newCart) {
this._cart = newCart;
this._saveCart();
}
get() {
return this._cart;
}
empty() {
this._cart = [];
this._saveCart();
}
/* Add product. If product AND subproduct combination exists,
we increment with provided quantity, otherwise it is
added as another line in the cart */
addProduct({ productId, quantity = 1, subProducts = [] }) {
const index = this._findProductIndex(productId);
if (index > -1) {
if (Cart._compareSubproducts(this._cart[index].subProducts, subProducts)) {
this._cart[index].quantity += quantity;
} else {
this._cart.push({ productId, quantity, subProducts });
}
} else {
this._cart.push({ productId, quantity, subProducts });
}
this._saveCart();
return this._cart;
}
/* Remove product. If product has more than provided quantity,
we just decrement by the provided quantity, otherwise we
remove the entire line */
removeProduct({ productId, quantity = 1 }) {
const index = this._findProductIndex(productId);
if (index > -1) {
if (this._cart[index].quantity <= quantity) {
this._cart.splice(index, 1);
} else {
this._cart[index].quantity -= quantity;
}
}
this._saveCart();
return this._cart;
}
addSubproduct(subProductId, productId, increaseQuantity = false) {
const index = this._findProductIndex(productId);
if (index < 0) return new Error('Product is not in cart');
this._cart[index].subProducts.push(subProductId);
// In case the sub product should be counted as separate product in the order
// we need to increase the quantity
if (increaseQuantity) {
this._cart[index].quantity += 1;
}
this._saveCart();
return this._cart;
}
removeSubproduct(subProductId, productId, decreaseQuantity = false) {
const index = this._findProductIndex(productId);
if (index < 0) return new Error('Product is not in cart');
const subProductIndex = this._cart[index].subProducts.indexOf(subProductId);
this._cart[index].subProducts.splice(subProductIndex, 1);
// In case the sub product should be counted as separate product in the order
// we need to increase/decrease the quantity
if (decreaseQuantity) {
this._cart[index].quantity -= 1;
}
this._saveCart();
return this._cart;
}
// Give orderId only if checkout failed during pay due to SCA
checkout(paymentMethodId, deliveryAddress, resumeOrderId) {
if (!this._isCartValid()) throw new Error('Cart not valid');
if (!paymentMethodId) throw new Error('Missing payment method');
const items = this._cart.map((item) => ({
product: item.productId,
quantity: item.quantity,
sub_products: item.subProducts,
}));
const payForOrder = (order) => new Payments(this.request).create({
orders: [order.id],
payment_method: paymentMethodId,
}).then((payment) => {
this.empty();
return payment;
});
if (resumeOrderId) {
return payForOrder(new Order(this.request, { id: resumeOrderId }));
}
return new Orders(this.request).create({
items,
delivery_address: deliveryAddress,
}).then((newOrder) => payForOrder(newOrder));
}
}
module.exports = Cart;