/*
* Copyright 2008-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.ssbusy.controller.app;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.broadleafcommerce.common.exception.ServiceException;
import org.broadleafcommerce.common.media.domain.Media;
import org.broadleafcommerce.common.money.Money;
import org.broadleafcommerce.common.web.controller.BroadleafAbstractController;
import org.broadleafcommerce.core.catalog.domain.Category;
import org.broadleafcommerce.core.catalog.domain.CategoryImpl;
import org.broadleafcommerce.core.catalog.domain.CategoryProductXref;
import org.broadleafcommerce.core.catalog.domain.FeaturedProduct;
import org.broadleafcommerce.core.catalog.domain.Product;
import org.broadleafcommerce.core.catalog.domain.RelatedProduct;
import org.broadleafcommerce.core.catalog.domain.Sku;
import org.broadleafcommerce.core.catalog.service.CatalogService;
import org.broadleafcommerce.core.rating.domain.RatingSummary;
import org.broadleafcommerce.core.rating.service.RatingService;
import org.broadleafcommerce.core.rating.service.type.RatingType;
import org.broadleafcommerce.core.search.domain.ProductSearchCriteria;
import org.broadleafcommerce.core.search.domain.ProductSearchResult;
import org.broadleafcommerce.core.search.domain.SearchFacetDTO;
import org.broadleafcommerce.core.search.service.SearchService;
import org.broadleafcommerce.core.web.service.SearchFacetDTOService;
import org.broadleafcommerce.inventory.service.InventoryService;
import org.broadleafcommerce.profile.web.core.CustomerState;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.ssbusy.core.account.domain.MyCustomer;
import com.ssbusy.core.like.service.LikeService;
import com.ssbusy.core.product.domain.MyProduct;
/**
* mobile app request controller. all with jsonp support.
*
* @author Ju
*/
@Controller
@RequestMapping("/app")
public class AppController extends BroadleafAbstractController {
@Resource(name = "blCatalogService")
protected CatalogService catalogService;
@Resource(name = "blSearchService")
protected SearchService searchService;
@Resource(name = "blSearchFacetDTOService")
protected SearchFacetDTOService facetService;
@Resource(name = "blRatingService")
protected RatingService ratingService;
@Resource(name = "blInventoryService")
protected InventoryService inventoryService;
@Resource(name = "ssbLikeService")
protected LikeService likeService;
@Value("${category.nav.root.id}")
protected Long navCategoryRootId;
@Value("${category.floor.root.id}")
protected Long floorCategoryRootId;
@Value("${nowVersion}")
private String nowVersion;
private Map<Long, Category> cache = new HashMap<Long, Category>(2);
@RequestMapping("/list-categories")
@ResponseBody
public List<Map<String, Object>> listCategories() {
List<Category> cats = catalogService
.findActiveSubCategoriesByCategory(cachedCategoryById(navCategoryRootId));
if (cats != null && cats.size() > 0) {
// gets child categories in order ONLY if they are in the xref table
// and active
List<Map<String, Object>> results = new ArrayList<Map<String, Object>>(
cats.size());
for (Category cart : cats) {
Map<String, Object> c = new HashMap<String, Object>(2);
c.put("id", cart.getId());
c.put("name", cart.getName());
results.add(c);
}
return results;
}
return Collections.emptyList();
}
@RequestMapping("/search")
@ResponseBody
public List<Map<String, Object>> searchProucts(@RequestParam("q") String q,
HttpServletRequest request) throws ServiceException {
if (q == null || (q = q.trim()).length() == 0)
return Collections.emptyList();
List<SearchFacetDTO> availableFacets = searchService.getSearchFacets();
ProductSearchCriteria searchCriteria = facetService
.buildSearchCriteria(request, availableFacets);
ProductSearchResult result = searchService.findProductsByQuery(q,
searchCriteria);
facetService.setActiveFacetResults(result.getFacets(), request);
List<Product> products = result.getProducts();
MyCustomer c = (MyCustomer) CustomerState.getCustomer();
if (c != null && c.getRegion() != null)
products = inventoryService.filterProducts(products, c.getRegion()
.getFulfillmentLocations());
List<Map<String, Object>> ret = new ArrayList<Map<String, Object>>(1);
Map<String, Object> m = new HashMap<String, Object>(2);
ret.add(m);
m.put("name", q);
m.put("items", wrapProducts(products, false));
return ret;
}
/**
* @return List<楼层<楼层属性, 值>>
*/
@RequestMapping("/list-products")
@ResponseBody
public List<Map<String, Object>> listProucts(
@RequestParam(value = "category-id", required = false) Long categoryId,
@RequestParam(value = "sorter", required = false) String sorter) {
List<Category> cats = null;
if (categoryId != null) {
Category cat = catalogService.findCategoryById(categoryId);
if (cat != null) {
cats = Arrays.asList(cat);
}
}
if (cats == null) // 默认列楼层
cats = catalogService
.findActiveSubCategoriesByCategory(cachedCategoryById(floorCategoryRootId));
return wrapCategories(cats, sorter);
}
private List<Map<String, Object>> wrapCategories(List<Category> cats,
String sorter) {
List<Map<String, Object>> ret = new ArrayList<Map<String, Object>>(
cats.size());
for (Category cat : cats) {
List<Product> prods;
if ("rec".equals(sorter)) {
List<FeaturedProduct> ps = cat.getFeaturedProducts();
if (ps == null || ps.isEmpty())
prods = Collections.emptyList();
else {
prods = new ArrayList<Product>(ps.size());
for (FeaturedProduct fp : ps) {
Product p = fp.getProduct();
if (p == null)
continue;
prods.add(p);
}
}
} else if ("hot".equals(sorter) || "new".equals(sorter)) {
List<RelatedProduct> ps = "hot".equals(sorter) ? cat
.getCrossSaleProducts() : cat.getUpSaleProducts();
if (ps == null || ps.isEmpty())
prods = Collections.emptyList();
else {
prods = new ArrayList<Product>(ps.size());
for (RelatedProduct rp : ps) {
Product p = rp.getProduct();
if (p == null)
continue;
prods.add(p);
}
}
} else {// 默认排序
List<CategoryProductXref> xrefs = cat.getActiveProductXrefs();
if (xrefs == null || xrefs.isEmpty())
prods = Collections.emptyList();
else {
prods = new ArrayList<Product>(xrefs.size());
for (CategoryProductXref xref : xrefs) {
Product p = xref.getProduct();
if (p == null)
continue;
prods.add(p);
}
}
}
MyCustomer c = (MyCustomer) CustomerState.getCustomer();
if (c != null && c.getRegion() != null)
prods = inventoryService.filterProducts(prods, c.getRegion()
.getFulfillmentLocations());
if (prods.isEmpty())
continue;
Map<String, Object> m = new HashMap<String, Object>(3);
ret.add(m);
m.put("catId", cat.getId());
m.put("name", cat.getName());
m.put("items", wrapProducts(prods, false));
}
return ret;
}
@RequestMapping("/d/check-update")
@ResponseBody
public Map<String, Object> checkForUpdate(@RequestParam("version") String version) {
if(!"1.1".equals(version)) {
Map<String, Object> ret = new HashMap<String, Object>(1);
ret.put("update", "<a onclick='javascript:navigator.app.loadUrl(\"http://www.onxiao.com/d/app\", { openExternal:true});' style=\"font-size:15px;\">有新的版本可供下载,请点此升级</a>");
return ret;
}
return Collections.emptyMap();
}
@RequestMapping("/product")
@ResponseBody
public Map<String, Object> showProduct(@RequestParam("url") String prodUrl) {
Product product = catalogService.findProductByURI(prodUrl);
if (product == null)
return Collections.emptyMap();
Map<String, Object> map = wrapProduct(product, true);
return map;
}
private Map<String, Object> wrapProduct(Product p, boolean detail) {
Sku defSku = p.getDefaultSku();
if (defSku == null || !defSku.isActive())
return null;
Map<String, Object> m = new HashMap<String, Object>(20);
m.put("id", p.getId());
m.put("name", p.getName());
m.put("saleNum", 50);
m.put("desc", p.getDescription());
m.put("longDesc", p.getLongDescription());
m.put("url", p.getUrl());
m.put("skuId", defSku.getId());
m.put("retailPrice", defSku.getRetailPrice());
m.put("salePrice", defSku.getSalePrice());
m.put("retailPrice", defSku.getRetailPrice());
Map<String, Media> medias = p.getMedia();
if (medias != null) {
if (detail) {
m.put("medias", medias.values());
} else {
Media media = medias.get("primary");
if (media != null) {
m.put("media", media);
}
}
}
if (p instanceof MyProduct) {
m.put("totalLike", ((MyProduct) p).getTotalLike());
m.put("totalSaled", ((MyProduct) p).getTotalSaled());
}
// 规格
if (detail) {
RatingSummary rating = ratingService.readRatingSummary(p.getId()
.toString(), RatingType.PRODUCT);
m.put("avgRating", rating == null ? 5 : rating.getAverageRating());
if (p instanceof MyProduct) {
m.put("totalLike", ((MyProduct) p).getTotalLike());
m.put("totalSaled", ((MyProduct) p).getTotalSaled());
m.put("liked", likeService.queryLike(p, CustomerState
.getCustomer().getId()));
m.put("longDesc", p.getLongDescription());
}
List<Map<String, Object>> more = new ArrayList<Map<String, Object>>();
m.put("skus", more);
Map<String, Object> wrapSku = wrapSku(defSku);
wrapSku.put("name", "单价");
more.add(wrapSku);
List<Sku> skus = p.getSkus();
if (skus != null && skus.size() > 0) {
for (Sku sku : skus) {
if (sku.getId().equals(defSku.getId()))
continue;
more.add(wrapSku(sku));
}
}
}
return m;
}
private Map<String, Object> wrapSku(Sku sku) {
Map<String, Object> s = new HashMap<String, Object>(3);
s.put("id", sku.getId());
s.put("name", sku.getName());
Money price = sku.getSalePrice() == null ? sku.getRetailPrice() : sku
.getSalePrice();
s.put("price", price);
return s;
}
private List<Map<String, Object>> wrapProducts(List<Product> ps,
boolean detail) {
if (ps == null || ps.isEmpty())
return Collections.emptyList();
List<Map<String, Object>> ret = new ArrayList<Map<String, Object>>(
ps.size());
for (Product p : ps) {
if (p == null)
continue;
Map<String, Object> m = wrapProduct(p, detail);
if (m != null)
ret.add(m);
}
return ret;
}
private Category cachedCategoryById(Long id) {
Category category = cache.get(id);
if (category == null) {
cache.put(id, category = new CategoryImpl());
category.setId(id);
}
return category;
}
}