UNPKG

@zhiguang-gastrofy/capi

Version:

comany apis, including Northfork api and Gastrofy api

285 lines (243 loc) 8.1 kB
import { HttpService } from './http.service'; import { parseImage, parsePrice, decimalPrice } from './utils'; import axios from 'axios'; const CancelToken = axios.CancelToken; export class ResolveService { private _NFHttp: any; private _mainCancel: Function; private _recipes:any; total:any = {}; products = []; ingredients = []; resolving:boolean = false; constructor( config?:any ) { config = { ...config || {} }; this._NFHttp = new HttpService( { ...{ host: 'https://api.northfork.se/api', }, ...config } ); } cancel( type?:string ) { if( ( !type || type ==='main' ) && this._mainCancel ) this._mainCancel(); if( !type || type ==='diff' ) { } } /** * the recipe id can be gastrofy_id or external_id: * { gastrofy_id: 1, portions: 1 } * OR * { external_id: 1, portions: 1 } * * options: { * tags: Array, * storeProvider: String, * storeIdentifier: String', * productExceptions: Array, * calculation: price | waste, * prioritization: String, * promotedBrand: String, * params: {} * } */ resolve( recipes:any, options:any ) { this.resolving = true; return this._NFHttp.post( 'smart-cart/recipes/resolve', { recipes: recipes, store: { tags: options.tags || [], provider: options.storeProvider, identifier: options.storeIdentifier, }, options: { calculation: options.calculation, prioritization:options.prioritization, product_exceptions: options.productExceptions, }, }, { params: options.params, promoted_brand: options.promotedBrand, cancelToken: new CancelToken( ( c:any ) => { this._mainCancel = c; } ), } ).then( ( res:any ) => { this.resolving = false; let data = res.data; this.products = this._formatProducts( data.products ); this.ingredients = this._formaIngredients( data.recipes ); this._recipes = data.recipes; this._calculateTotal(); return this; }, ( err:any ) => { this.resolving = false; return err; } ); } // substitute can be new quantity or new product substituteProduct( identifier:string, substitute:any ) { let original = null; for( let product of this.products ) { if( product.substitute_identifier === identifier ) { original = product; break; } } if( !original ) return; // TODO: TO FIX: // NOTE: The consumption of the replaced product is 0 from api, so set to 0 at frontend now original.consumption = 0; original.replaced = true; if( typeof substitute === 'number' ) { original.quantity = substitute; } else { for( let field in original ) { if( field === 'substitute_identifier' || typeof substitute[field] === 'undefined' ) continue; original[field] = substitute[field]; } } this._calculateTotal(); } productsBySections() { let sharedProducts = []; let commonProducts = []; let recipesProducts = []; for( let product of this.products ) { if( product.common ) commonProducts.push( product ); else if( product.shared ) sharedProducts.push( product ); else recipesProducts.push( product ); } return { common: commonProducts, shared: sharedProducts, recipes: this._recipes.map( ( recipe:any ) => { let recipeProducts = []; for( let ingredient of recipe.ingredients ) { for( let product of recipesProducts ) { for( let ingredientId of product.recipe_ingredient_ids ) { if( ingredientId !== ingredient.id ) continue; recipeProducts.push( product ); } } } return { id: recipe.id, title: recipe.title, portions: recipe.portions, image_url: parseImage( recipe ), products: recipeProducts, }; } ), }; } productsByCategories() { let index = {}; let result = []; for( let product of this.products ) { const category = product.categories[0] || { id: -1, sort_order: 999999999, title: null }; const categoryId = category.id; let productIndex = index[ categoryId ]; if( productIndex === undefined ) { productIndex = result.length; index[categoryId] = productIndex; result[productIndex] = { id: category.id, title: category.title, sort_order: category.sort_order, products: [], }; } result[productIndex].products.push( product ); } result.sort( ( a:any, b:any ) => { if( a.sort_order > b.sort_order ) return 1; return -1; } ); return result; } private _formatProducts( data ) { let products = []; for( let productGroup of data ) { products = products.concat( productGroup.map( ( product:any ) => { product.brand = product.brand && product.brand !== 'na'? product.brand: null; product.price = parsePrice( product.price ); product.is_active = product.price>0&&(product.strategy!=='out_of_stock'&&product.strategy!=='replaced_out_of_stock'); product.replaced = product.strategy === 'replaced' || product.strategy === 'replaced_out_of_stock'; product.recipe_ingredient_ids = product.recipe_ingredient_ids.map( item => item.id ); product.common = product.common === true; product.shared = product.recipe_ingredient_ids.length > 1; product.name = product.name.trim(); delete product.strategy; delete product.partner_attributes; delete product.ean; delete product.sub_text; product.ingredients = ( ( ids:any ) => { return () => { return ids.map( ( id:any ) => { for( let ingredient of this.ingredients ) { if( ingredient.id === id ) return ingredient; } } ); }; } )( product.recipe_ingredient_ids ); return product; } ) ); } return products; } private _formaIngredients( recipes:any ) { let ingredients = []; for( let recipe of recipes ) { ingredients = ingredients.concat( recipe.ingredients.map( ( ingredient:any ) => { ingredient.amount = ingredient.amount.replace( /(\.\w)0$/, ( v:any, m:any ) => { return m > 0 ? m: ''; } ); ingredient.products = ( ( ingredientId:number ) => { return () => { let result = []; for( let product of this.products ) { for( let id of product.recipe_ingredient_ids ) { if( id === ingredientId ) { result.push( product ); break; } } } return result; }; } )( ingredient.id ); return ingredient; } ) ); } return ingredients; } private _calculateTotal() { let total = { price: 0, price_with_common: 0, consumption_price: 0, consumption_price_with_common: 0, quantity: 0, quantity_with_common: 0, checkout_price: 0, checkout_quantity: 0, }; for( let product of this.products ) { const curTotal = product.price * product.quantity; const consumptionPrice = curTotal * product.consumption; total.price_with_common += curTotal; total.consumption_price_with_common += consumptionPrice; total.quantity_with_common += product.quantity; if( !product.common || product.replaced ) { total.price += curTotal; total.consumption_price += consumptionPrice; total.quantity += product.quantity; product.quantity = product.quantity; if( product.is_active ) { total.checkout_price += curTotal; total.checkout_quantity += product.quantity; } } } for( let totalField in total ) { this.total[totalField] = decimalPrice( total[ totalField ] ); } } }