private Hashtable<Long, TradeEntity> getLongTradeEntityHashtable(List<Trade> trades) {
   Hashtable<Long, TradeEntity> existed = new Hashtable<Long, TradeEntity>();
   List<Long> tids = new ArrayList<Long>();
   for (Trade trade : trades) {
     tids.add(trade.getTid());
   }
   Collection entities = tradeEntityRepository.findTradeEntitiesByTids(tids);
   for (Object o : entities) {
     TradeEntity e = (TradeEntity) o;
     existed.put(e.getTid(), e);
   }
   return existed;
 }
  private Date getQueryStartDate(Visitor visitor) {
    Date minCreated =
        tradeEntityRepository.findMinCreatedBySellerIdAndNotStatus(
            visitor.getVisitorId(), Arrays.asList(com.wiysoft.report.Constants.FINAL_TRADE_STATUS));
    if (minCreated == null) {
      minCreated = new Date(0);
    }
    Date now = now();
    Calendar c = Calendar.getInstance();
    c.setTime(now);
    c.add(Calendar.MONTH, -3);
    now = c.getTime();

    Date createdStart = minCreated;
    if (now.after(minCreated)) {
      createdStart = now;
    }
    return createdStart;
  }
  public void syncTrades(Visitor visitor) {
    if (visitor == null) {
      return;
    }
    long pageSize = 50;
    String sessionKey = visitor.getSessionKey();
    if (StringUtils.isEmpty(sessionKey)) {
      return;
    }

    Date createdStart = getQueryStartDate(visitor);

    logger.debug(
        String.format(
            "About to synchronize trades for %s since %s",
            visitor.getVisitorNick(), createdStart.toString()));

    DefaultTaobaoClient client =
        new DefaultTaobaoClient(
            wiyReportConfiguration.getRestfulApi(),
            wiyReportConfiguration.getAppKey(),
            wiyReportConfiguration.getAppSecret(),
            Constants.FORMAT_JSON,
            30000,
            300000);

    TradesSoldGetRequest req = new TradesSoldGetRequest();
    req.setUseHasNext(true);
    req.setStartCreated(createdStart);
    req.setPageSize(pageSize);
    req.setFields(
        "seller_nick,buyer_nick,title,type,created,sid,tid,seller_rate,buyer_rate,status,payment,discount_fee,adjust_fee,post_fee,total_fee,pay_time,end_time,modified,consign_time,buyer_obtain_point_fee,point_fee,real_point_fee,received_payment,commission_fee,pic_path,num_iid,num_iid,num,price,cod_fee,cod_status,shipping_type,receiver_name,receiver_state,receiver_city,receiver_district,receiver_address,receiver_zip,receiver_mobile,receiver_phone,orders.title,orders.pic_path,orders.price,orders.num,orders.iid,orders.num_iid,orders.sku_id,orders.refund_status,orders.status,orders.oid,orders.total_fee,orders.payment,orders.discount_fee,orders.adjust_fee,orders.sku_properties_name,orders.item_meal_name,orders.buyer_rate,orders.seller_rate,orders.outer_iid,orders.outer_sku_id,orders.refund_id,orders.seller_type");
    try {
      long pageNumber = 1;
      while (true) {
        req.setPageNo(pageNumber);

        TradesSoldGetResponse response = client.execute(req, sessionKey);
        List<Trade> trades = response.getTrades();

        if (trades != null) {
          Hashtable<Long, TradeEntity> existed = getLongTradeEntityHashtable(trades);

          for (Trade trade : trades) {
            TradeEntity entity = EntityBuilder.buildTradeEntity(trade, visitor.getVisitorId());

            if (existed.containsKey(trade.getTid())) {
              TradeEntity existedTradeEntity = existed.get(trade.getTid());
              EntityBuilder.updateTradeEntity(existedTradeEntity, entity);
              entity = existedTradeEntity;
            }

            tradeEntityRepository.save(entity);
          }
        }

        if (response.getHasNext() == null || !response.getHasNext()) {
          break;
        }
        ++pageNumber;
      }
    } catch (ApiException e) {
      logger.error(e.getMessage(), e);
    } finally {
      // rebuild consumer entities
      daoService.buildConsumersBy(visitor.getVisitorId());
      // rebuild product purchase
      Date today = Calendar.getInstance().getTime();
      Date yesterday = DateTimeUtils.dateAdjust(today, Calendar.DAY_OF_YEAR, -1);
      daoService.buildProductPurchaseForSeller(visitor.getVisitorId(), yesterday, today);
      // rebuild produce entities
      daoService.buildProductEntitiesForSeller(visitor.getVisitorId(), yesterday, today);
      // build product purchase combo measurements
      daoService.buildProductPurchaseComboMeasurements();

      logger.debug(CommonService.class.getCanonicalName() + " finished.");
    }
  }