UNPKG

@stackend/api

Version:

JS bindings to api.stackend.com

441 lines 17.5 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getLocalStorageCustomerInfoKey = exports.getCustomerInfo = exports.setCustomerType = exports.setCustomerCountryCode = exports.getShopCountryCode = exports.getCartTotalPriceIncludingVAT = exports.getTotalPriceIncludingVAT = exports.getVATType = exports.multiplyPrice = exports.applyVat = exports.getPriceIncludingVAT = exports.useVATS = exports.getTradeRegion = exports.listCountries = exports.listVats = exports.getVats = exports.VatType = exports.percentToVatMultiplier = exports.vatMultiplierToPercent = exports.formatVatPercentage = exports.CustomerType = exports.TradeRegion = void 0; var api_1 = require("../api"); var graphql_1 = require("../util/graphql"); var shopActions_1 = require("./shopActions"); var getCountryCode_1 = require("../util/getCountryCode"); var TradeRegion; (function (TradeRegion) { /** Domestic trade */ TradeRegion["NATIONAL"] = "national"; /** Trade within EU, etc */ TradeRegion["REGIONAL"] = "regional"; /** Trade with the rest, etc */ TradeRegion["WORLDWIDE"] = "worldwide"; })(TradeRegion = exports.TradeRegion || (exports.TradeRegion = {})); var CustomerType; (function (CustomerType) { CustomerType["CONSUMER"] = "b2c"; CustomerType["BUSINESS"] = "b2b"; })(CustomerType = exports.CustomerType || (exports.CustomerType = {})); /** * Format 1.25 as 25% * @param vatMultiplier */ function formatVatPercentage(vatMultiplier) { return vatMultiplierToPercent(vatMultiplier) + '%'; } exports.formatVatPercentage = formatVatPercentage; /** * Convert a vat multiplier to a percentage * @param vatMultiplier */ function vatMultiplierToPercent(vatMultiplier) { return Math.round(100 * (vatMultiplier - 1)); } exports.vatMultiplierToPercent = vatMultiplierToPercent; /** * Convert a percentage (25%) to a vat multiplier (1.25) * @param percent */ function percentToVatMultiplier(percent) { return 1 + percent / 100; } exports.percentToVatMultiplier = percentToVatMultiplier; var VatType; (function (VatType) { VatType["STANDARD"] = "standardRate"; VatType["REDUCED"] = "reducedRate"; VatType["REDUCED_ALT"] = "reducedRateAlt"; VatType["SUPER_REDUCED"] = "superReducedRate"; VatType["PARKING"] = "parkingRate"; })(VatType = exports.VatType || (exports.VatType = {})); /** * Get VATs for a country. Will try to use the stacks default country if not specified. * @param shopCountryCode * @returns {Thunk<XcapJsonResult>} */ function getVats(_a) { var shopCountryCode = _a.shopCountryCode; return (0, api_1.getJson)({ url: '/shop/vat/get-vats', parameters: arguments }); } exports.getVats = getVats; /** * Get all supported VATs. * @returns {Thunk<XcapJsonResult>} */ function listVats() { return (0, api_1.getJson)({ url: '/shop/vat/list', parameters: arguments }); } exports.listVats = listVats; /** * Get all countries. * @returns {Thunk<ListCountriesResult>} */ function listCountries() { return (0, api_1.getJson)({ url: '/shop/vat/list-countries', parameters: arguments }); } exports.listCountries = listCountries; /** * Get the trade region * @returns {Thunk<XcapJsonResult>} */ function getTradeRegion(_a) { var customerCountryCode = _a.customerCountryCode, shopCountryCode = _a.shopCountryCode; return (0, api_1.getJson)({ url: '/shop/vat/get-trade-region', parameters: arguments }); } exports.getTradeRegion = getTradeRegion; /** * Should VATs be used? * @param shopState * @param customerType * @param tradeRegion */ function useVATS(_a) { var shopState = _a.shopState, customerType = _a.customerType, tradeRegion = _a.tradeRegion; if (!shopState.vats || !shopState.vats.showPricesUsingVAT) { return false; } var typeOfCustomer = customerType || shopState.vats.customerType || CustomerType.CONSUMER; var region = tradeRegion || shopState.vats.customerTradeRegion || TradeRegion.NATIONAL; if ( /* No VAT charged to international customers */ region === TradeRegion.WORLDWIDE || /* No VAT charged to b2b customer within the region */ (region == TradeRegion.REGIONAL && typeOfCustomer == CustomerType.BUSINESS)) { return false; } return true; } exports.useVATS = useVATS; /** * Get the price including vat. * Supply the price, a product variant or get the minVariantPrice of the product. * @param shopState * @param product * @param productVariant * @param customerType * @param tradeRegion * @param price Optional price. Overrides the product and product variant price if supplied. * @param quantity Optional quantity, defaults to 1 */ function getPriceIncludingVAT(_a) { var shopState = _a.shopState, product = _a.product, productVariant = _a.productVariant, customerType = _a.customerType, tradeRegion = _a.tradeRegion, price = _a.price, _b = _a.quantity, quantity = _b === void 0 ? 1 : _b; var p = null; if (price) { p = price; } else { if (productVariant) { p = productVariant.price; } else { p = product.priceRange.minVariantPrice; //getLowestVariantPrice(product); } } if (!useVATS({ shopState: shopState, customerType: customerType, tradeRegion: tradeRegion })) { return multiplyPrice(p, quantity); } // Check if there is a VAT exception for any of the collections the product belongs to var vatType = getVATType(shopState, product); return applyVat(shopState, vatType, p, quantity); } exports.getPriceIncludingVAT = getPriceIncludingVAT; /** * Apply VAT to the price * @param shopState * @param vatType * @param price * @param quantity */ function applyVat(shopState, vatType, price, quantity) { if (quantity === void 0) { quantity = 1; } if (!shopState.vats) { return multiplyPrice(price, quantity); } if (!shopState.vats.vatRates) { console.warn('Stackend: VAT rates not available.'); return multiplyPrice(price, quantity); } var rate = shopState.vats.vatRates[vatType]; if (!rate) { rate = shopState.vats.vatRates[VatType.STANDARD]; if (!rate) { return multiplyPrice(price, quantity); } } if (typeof rate !== 'number') { return multiplyPrice(price, quantity); } return multiplyPrice(price, quantity * (1 + rate / 100)); } exports.applyVat = applyVat; function multiplyPrice(price, factor) { if (factor === 1) { return price; } return { amount: String(parseFloat(price.amount) * factor), currencyCode: price.currencyCode }; } exports.multiplyPrice = multiplyPrice; /** * Get the vat type for a product * @param shopState * @param product */ function getVATType(shopState, product) { var vatType = VatType.STANDARD; var vats = shopState.vats; if (vats && product && product.collections) { (0, graphql_1.forEachGraphQLList)(product.collections, function (i) { var v = vats.overrides[i.handle]; if (v) { vatType = v; } }); } return vatType; } exports.getVATType = getVATType; /** * Get the total price for a checkout * @param shopState * @param checkout * @param customerType * @param tradeRegion */ function getTotalPriceIncludingVAT(_a) { var shopState = _a.shopState, checkout = _a.checkout, customerType = _a.customerType, tradeRegion = _a.tradeRegion; var total = 0; (0, graphql_1.forEachGraphQLList)(checkout.lineItems, function (i) { var pv = (0, shopActions_1.getProductAndVariant)(shopState, i); if (pv) { var p = getPriceIncludingVAT({ shopState: shopState, product: pv.product, productVariant: pv.variant, quantity: i.quantity, customerType: customerType, tradeRegion: tradeRegion }); total += parseFloat(p.amount); } }); return { amount: String(total), currencyCode: checkout.currencyCode }; } exports.getTotalPriceIncludingVAT = getTotalPriceIncludingVAT; /** * Get the total price for a cart * @param shopState * @param cart * @param customerType * @param tradeRegion */ function getCartTotalPriceIncludingVAT(_a) { var shopState = _a.shopState, cart = _a.cart, customerType = _a.customerType, tradeRegion = _a.tradeRegion; var total = 0; (0, graphql_1.forEachGraphQLList)(cart.lines, function (i) { var pv = (0, shopActions_1.getProductAndVariant2)(shopState, i.merchandise.product.handle, i.merchandise.id); if (pv) { var p = getPriceIncludingVAT({ shopState: shopState, product: pv.product, productVariant: pv.variant, quantity: i.quantity, customerType: customerType, tradeRegion: tradeRegion }); total += parseFloat(p.amount); } }); return { amount: String(total), currencyCode: cart.estimatedCost.totalAmount.currencyCode }; } exports.getCartTotalPriceIncludingVAT = getCartTotalPriceIncludingVAT; /** * Get the shops country code, fall back to the locale or 'EN' if not set. */ function getShopCountryCode() { var _this = this; return function (dispatch, getState) { return __awaiter(_this, void 0, void 0, function () { var _a, shop, communities, cc; return __generator(this, function (_b) { _a = getState(), shop = _a.shop, communities = _a.communities; // Load the vats, if available from the community if (!shop.vats) { if (!communities.community) { throw 'No current community'; } dispatch((0, shopActions_1.setCommunityVATS)(communities.community)); shop = getState(); if (!shop.vats) { console.error("Stackend: Can't get shop country: No VAT data set up"); } } if (shop.vats && shop.vats.shopCountryCode) { return [2 /*return*/, shop.vats.shopCountryCode]; } if (!communities.community) { throw 'No current community'; } if (communities.community.locale) { cc = (0, getCountryCode_1.getCountryCode)(communities.community.locale); if (cc) { return [2 /*return*/, cc]; } } console.error("Stackend: Can't get shop country: No VAT or community locale set up. Falling back to EN"); return [2 /*return*/, 'EN']; }); }); }; } exports.getShopCountryCode = getShopCountryCode; /** * Set the customers country code and update trade region accordingly * @param customerCountryCode */ function setCustomerCountryCode(customerCountryCode) { var _this = this; return function (dispatch, getState) { return __awaiter(_this, void 0, void 0, function () { var _a, shop, communities, shopCountryCode, tradeRegion, r, customerType, ci; return __generator(this, function (_b) { switch (_b.label) { case 0: _a = getState(), shop = _a.shop, communities = _a.communities; shopCountryCode = dispatch(getShopCountryCode()); customerCountryCode = customerCountryCode.toUpperCase(); tradeRegion = TradeRegion.NATIONAL; if (!(customerCountryCode === shopCountryCode)) return [3 /*break*/, 1]; tradeRegion = TradeRegion.NATIONAL; return [3 /*break*/, 3]; case 1: return [4 /*yield*/, dispatch(getTradeRegion({ customerCountryCode: customerCountryCode }))]; case 2: r = _b.sent(); if (r.error) { console.error('Stackend: failed to get trade region for ' + customerCountryCode + ': ' + (0, api_1.getJsonErrorText)(r)); return [2 /*return*/]; } tradeRegion = r.tradeRegion.toLowerCase(); // To match js _b.label = 3; case 3: customerType = (shop === null || shop === void 0 ? void 0 : shop.vats.customerType) || CustomerType.CONSUMER; if (localStorage) { ci = { customerCountryCode: customerCountryCode, tradeRegion: tradeRegion, customerType: customerType }; localStorage.setItem(getLocalStorageCustomerInfoKey(communities.community), JSON.stringify(ci)); } dispatch((0, shopActions_1.setCustomerVatInfo)({ customerCountryCode: customerCountryCode, customerTradeRegion: tradeRegion, customerType: customerType })); return [2 /*return*/]; } }); }); }; } exports.setCustomerCountryCode = setCustomerCountryCode; /** * Set the type of customer * @param customerType */ function setCustomerType(customerType) { var _this = this; return function (dispatch, getState) { return __awaiter(_this, void 0, void 0, function () { var communities, ci; return __generator(this, function (_a) { communities = getState().communities; ci = dispatch(getCustomerInfo()); if (ci && localStorage) { ci.customerType = customerType; localStorage.setItem(getLocalStorageCustomerInfoKey(communities.community), JSON.stringify(ci)); } dispatch((0, shopActions_1.setCustomerVatInfo)({ customerType: customerType })); return [2 /*return*/]; }); }); }; } exports.setCustomerType = setCustomerType; /** * Get customer info from shop.vats, with fallback to local storage */ function getCustomerInfo() { return function (dispatch, getState) { var _a = getState(), shop = _a.shop, communities = _a.communities; if (shop.vats && shop.vats.tradeRegion) { return { customerCountryCode: shop.vats.customerCountryCode, tradeRegion: shop.vats.tradeRegion, customerType: shop.vats.customerType || CustomerType.CONSUMER }; } if (localStorage) { var cc = localStorage.getItem(getLocalStorageCustomerInfoKey(communities.community)); if (cc) { return JSON.parse(cc); } } return null; }; } exports.getCustomerInfo = getCustomerInfo; function getLocalStorageCustomerInfoKey(community) { return community.permalink + '-customer'; } exports.getLocalStorageCustomerInfoKey = getLocalStorageCustomerInfoKey; //# sourceMappingURL=vat.js.map