|
@@ -1,6 +1,7 @@
|
|
|
package com.parksong.services.delivery.impl;
|
|
|
|
|
|
import com.alibaba.fastjson.JSON;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
import com.parksong.basics.beans.BatchDataMsg;
|
|
|
import com.parksong.basics.exception.AskException;
|
|
|
import com.parksong.basics.exception.BusinessException;
|
|
@@ -28,11 +29,13 @@ import com.parksong.services.delivery.*;
|
|
|
import com.parksong.services.express.ExpressConsumeService;
|
|
|
import com.parksong.services.sms.SmsService;
|
|
|
import com.parksong.services.store.*;
|
|
|
+import com.parksong.util.ExcelUtil;
|
|
|
import com.parksong.util.RegexUtil;
|
|
|
import com.parksong.util.bacth.BatchDataHandleUtil;
|
|
|
import com.parksong.util.enums.DeliverySignReturnEnum;
|
|
|
+import com.parksong.util.enums.ExpressStatusEnum;
|
|
|
import com.parksong.util.enums.SMSErrorCodeEnum;
|
|
|
-import com.parksong.util.txt.TxtUtils;
|
|
|
+import com.parksong.util.enums.SmsSendStatusEnum;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
import org.apache.logging.log4j.util.Strings;
|
|
@@ -42,10 +45,15 @@ import org.springframework.context.annotation.Lazy;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
import org.springframework.transaction.interceptor.TransactionAspectSupport;
|
|
|
+import org.springframework.util.CollectionUtils;
|
|
|
|
|
|
+import javax.servlet.http.HttpServletResponse;
|
|
|
+import java.text.NumberFormat;
|
|
|
import java.text.ParseException;
|
|
|
import java.text.SimpleDateFormat;
|
|
|
+import java.time.Duration;
|
|
|
import java.time.LocalDate;
|
|
|
+import java.time.ZoneId;
|
|
|
import java.time.format.DateTimeFormatter;
|
|
|
import java.util.*;
|
|
|
import java.util.concurrent.CompletableFuture;
|
|
@@ -245,6 +253,9 @@ public class DeliverysServiceImpl extends BasicsService implements DeliverysServ
|
|
|
delivery.getStatus().compareTo(DeliveryStatusConstants.ORDER_STATUS_COMPLETE) == 0) {
|
|
|
throw new BusinessException("订单已出库,请勿重复签收!");
|
|
|
}
|
|
|
+ if (!CollectionUtils.isEmpty(filter.getExpSignPhotos())){
|
|
|
+ delivery.setSignPhotoUrl(StringUtils.join(filter.getExpSignPhotos(), ","));
|
|
|
+ }
|
|
|
delivery.setStoreId(storeId);
|
|
|
Delivery entity = new Delivery();
|
|
|
BeanUtils.copyProperties(delivery, entity);
|
|
@@ -462,9 +473,9 @@ public class DeliverysServiceImpl extends BasicsService implements DeliverysServ
|
|
|
if (null == data.getDeliveryId() || null == data.getStoreId()) {
|
|
|
throw new BusinessException("不合法的参数");
|
|
|
}
|
|
|
- if (!Strings.isBlank(data.getShelfCode()) && data.getShelfCode().length() > 9) {
|
|
|
+ /*if (!Strings.isBlank(data.getShelfCode()) && data.getShelfCode().length() > 9) {
|
|
|
throw new BusinessException("取件码不能大于9位");
|
|
|
- }
|
|
|
+ }*/
|
|
|
if(Strings.isNotBlank(data.getUserPhone())){
|
|
|
boolean userPhoneValid = RegexUtil.isValidPhoneNumberCN(data.getUserPhone())
|
|
|
|| Constants.DEFAULT_MOBILE_KB.equals(data.getUserPhone());
|
|
@@ -631,6 +642,181 @@ public class DeliverysServiceImpl extends BasicsService implements DeliverysServ
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public StatisticsOutboundRate outboundRate(DeliveryFilter filter) {
|
|
|
+ // 创建一个数值格式化对象
|
|
|
+ NumberFormat numberFormat = NumberFormat.getInstance();
|
|
|
+ // 设置精确到小数点后2位
|
|
|
+ numberFormat.setMaximumFractionDigits(2);
|
|
|
+ List<StatisticsOutboundRate> queryData = getQueryData(filter.getStoreId(), filter.getBeginTime(), filter.getEndTime(), filter.getExpId(), numberFormat);
|
|
|
+ StatisticsOutboundRate totalData = getTotalData(queryData, numberFormat);
|
|
|
+ return totalData;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void export(HttpServletResponse response, DeliveryFilter filter) {
|
|
|
+ List<StatisticsOutboundRate> queryData = getQueryData(filter.getStoreId(), filter.getBeginTime(), filter.getEndTime(), null, null);
|
|
|
+ ExcelUtil.exportExpressData(response, queryData);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<PhoneLibDto> getConsigneeInfoByPhone(DeliveryFilter filter) {
|
|
|
+ List<PhoneLibDto> phoneLibDtoList = deliverysDao.getConsigneeInfoByPhone(filter);
|
|
|
+ if (StringUtils.isNotBlank(filter.getConsigneePhoneEnd())){
|
|
|
+ phoneLibDtoList.stream().forEach(phoneLibDto -> phoneLibDto.setNamePhone(phoneLibDto.getConsingeeName() + "--" + phoneLibDto.getConsingeePhone()));
|
|
|
+ }
|
|
|
+ return phoneLibDtoList;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Delivery storageDeliveryNew(DeliveryFilter filter, String appVersion, String apiVersion) {
|
|
|
+ Delivery delivery = new Delivery();
|
|
|
+ CacheTool cacheTool = new CacheTool("inDelivery:count");
|
|
|
+ Map<Integer, List<WhiteList>> map = whiteListService.getMapByStoreId(filter.getStoreId());
|
|
|
+ Store store = storeService.getStoreById(filter.getStoreId());
|
|
|
+ User user = filter.getUser();
|
|
|
+ log.info("入库门店:" + store.getShortName() + "------->入库用户:" + user.getUserName());
|
|
|
+ StorageDeliveryFilter storageDeliveryFilter = filter.getDeliverys().get(0);
|
|
|
+ //处理取件码
|
|
|
+ dealWithShelfCode(filter.getStoreId(), storageDeliveryFilter);
|
|
|
+ this.storageDelivery(filter, appVersion, apiVersion, storageDeliveryFilter, cacheTool, map, store, user);
|
|
|
+ delivery.setShelfCode(storageDeliveryFilter.getShelfCode());
|
|
|
+ return delivery;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Delivery expressDetailInfo(DeliveryFilter filter) {
|
|
|
+ Delivery delivery = deliverysDao.expressDetailInfo(filter.getDeliveryId(), filter.getStoreId());
|
|
|
+ if (delivery.getStatus() == 126 || delivery.getStatus() == 246){
|
|
|
+ //相隔时间
|
|
|
+ Duration duration = Duration.between(delivery.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(), delivery.getStatusTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
|
|
|
+ delivery.setWarehousingTime(duration.toDays());
|
|
|
+ }else {
|
|
|
+ delivery.setStatusTime(null);
|
|
|
+ delivery.setWarehousingTime(0L);
|
|
|
+ }
|
|
|
+ delivery.setStatusName(ExpressStatusEnum.valueOf(delivery.getStatus()).getValue());
|
|
|
+ delivery.setSmsStatusName(SmsSendStatusEnum.valueOf(delivery.getSmsStatus()).getValue());
|
|
|
+ if (StringUtils.isNotBlank(delivery.getSignPhotoUrl())){
|
|
|
+ delivery.setSignPhotoUrlList(Arrays.asList(delivery.getSignPhotoUrl().split(",")));
|
|
|
+ }
|
|
|
+
|
|
|
+ List<ExpressOperation> expressOperationList = deliverysDao.selectExpressOperationRecord(filter.getStoreId(), delivery.getExpcode());
|
|
|
+ for (ExpressOperation expressOperation : expressOperationList) {
|
|
|
+ String createTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(expressOperation.getCreateTime());
|
|
|
+ DeliveryFilter build = DeliveryFilter.builder()
|
|
|
+ .storeId(expressOperation.getStoreId())
|
|
|
+ .expCode(expressOperation.getExpcode())
|
|
|
+ .build();
|
|
|
+ Delivery delivery1 = deliverysDao.queryDeliveryByIdOrExpCode(build);
|
|
|
+ if (expressOperation.getStatus() == 0) {
|
|
|
+ expressOperation.setTitle(ExpressStatusEnum.valueOf(expressOperation.getStatus()).getValue() + SmsSendStatusEnum.valueOf(delivery1.getSmsStatus()).getValue());
|
|
|
+ expressOperation.setOperationContent(createTime + " 操作人:" + delivery1.getDeliveryUname());
|
|
|
+ } else {
|
|
|
+ expressOperation.setTitle(ExpressStatusEnum.valueOf(expressOperation.getStatus()).getValue() + "成功");
|
|
|
+ if (expressOperation.getStatus() == 122){
|
|
|
+ expressOperation.setOperationContent(createTime + " 操作人:" + delivery1.getDeliveryUname());
|
|
|
+ }else {
|
|
|
+ expressOperation.setOperationContent(createTime + " 操作人:" + delivery1.getDeliveryUid());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ delivery.setExpressOperationList(expressOperationList);
|
|
|
+ return delivery;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean addSenderInfo(DeliveryFilter filter) {
|
|
|
+ if (StringUtils.isBlank(filter.getSenderPhone())){
|
|
|
+ throw new BusinessException("寄件人电话号码不能为空");
|
|
|
+ }
|
|
|
+ deliverysDao.addSenderInfo(filter);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void dealWithShelfCode(Integer storeId, StorageDeliveryFilter storageDeliveryFilter) {
|
|
|
+ CacheTool shelfcodeCacheTool = CacheTool.initShelfcodeCacheTool();
|
|
|
+ String day = String.format("%02d", LocalDate.now().getDayOfMonth());
|
|
|
+ String redisKey = storeId + ":" + day + ":" + storageDeliveryFilter.getShelfId();
|
|
|
+ String number = String.format("%03d", shelfcodeCacheTool.incrBy(redisKey, 1).intValue());
|
|
|
+ StoreShelf storeShelf = storeShelfService.getById(storageDeliveryFilter.getShelfId());
|
|
|
+ //取件码 货架号 + 当天日期 + 三位自增长
|
|
|
+ storageDeliveryFilter.setShelfCode(storeShelf.getShelfName() + "-" + day + "-" + number);
|
|
|
+ //是否存在相同取货码+在库的快递
|
|
|
+ if (deliverysDao.selectDelivery(storeId, storageDeliveryFilter.getShelfCode()) > 0){
|
|
|
+ throw new BusinessException("库中存在相同取件码,请及时处理:" + storageDeliveryFilter.getShelfCode());
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private StatisticsOutboundRate getTotalData(List<StatisticsOutboundRate> queryData, NumberFormat numberFormat) {
|
|
|
+ StatisticsOutboundRate totalData = StatisticsOutboundRate.builder()
|
|
|
+ .outboundNum(0)
|
|
|
+ .warehousing(0)
|
|
|
+ .waitOutboundNum(0)
|
|
|
+ .sendBackNum(0)
|
|
|
+ .outboundRate("0%")
|
|
|
+ .detailInfo(queryData)
|
|
|
+ .build();
|
|
|
+ if (org.apache.commons.collections.CollectionUtils.isNotEmpty(queryData)){
|
|
|
+ queryData.stream().forEach(data -> {
|
|
|
+ totalData.setWarehousing(totalData.getWarehousing() + data.getWarehousing());
|
|
|
+ totalData.setOutboundNum(totalData.getOutboundNum() + data.getOutboundNum());
|
|
|
+ });
|
|
|
+ totalData.setWaitOutboundNum(totalData.getWarehousing() - totalData.getOutboundNum());
|
|
|
+ if(totalData.getWarehousing() == 0){
|
|
|
+ totalData.setOutboundRate("0%");
|
|
|
+ }else {
|
|
|
+ totalData.setOutboundRate(numberFormat.format((float) totalData.getOutboundNum() / (float) totalData.getWarehousing() * 100) + "%");
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ return totalData;
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<StatisticsOutboundRate> getQueryData(Integer storeId, String beginTime, String endTime, Integer expId, NumberFormat numberFormat) {
|
|
|
+ List<StatisticsOutboundRate> queryData = new ArrayList<>();
|
|
|
+ List<String> timeList = deliverysDao.historyTime(storeId, beginTime, endTime);
|
|
|
+ timeList.stream().forEach(time -> {
|
|
|
+ queryData.add(getTodayData(storeId, time, expId, numberFormat));
|
|
|
+ });
|
|
|
+ return queryData;
|
|
|
+ }
|
|
|
+
|
|
|
+ private StatisticsOutboundRate getTodayData(Integer storeId, String todayTime, Integer expId, NumberFormat numberFormat) {
|
|
|
+ StatisticsOutboundRate todayData = StatisticsOutboundRate.builder()
|
|
|
+ .time(todayTime)
|
|
|
+ .outboundNum(0)
|
|
|
+ .warehousing(0)
|
|
|
+ .waitOutboundNum(0)
|
|
|
+ .sendBackNum(0)
|
|
|
+ .outboundRate("0%")
|
|
|
+ .detailInfo(new ArrayList<>())
|
|
|
+ .build();
|
|
|
+ List<StatisticsOutboundRate> statisticsOutboundRates = deliverysDao.todayData(storeId, todayTime, expId);
|
|
|
+ if (org.apache.commons.collections.CollectionUtils.isNotEmpty(statisticsOutboundRates)){
|
|
|
+ statisticsOutboundRates.stream().forEach(statisticsOutboundRate -> {
|
|
|
+ statisticsOutboundRate.setWaitOutboundNum(statisticsOutboundRate.getWarehousing() - statisticsOutboundRate.getOutboundNum());
|
|
|
+ if (null !=numberFormat){
|
|
|
+ statisticsOutboundRate.setOutboundRate(numberFormat.format((float) statisticsOutboundRate.getOutboundNum() / (float) statisticsOutboundRate.getWarehousing() * 100) + "%");
|
|
|
+ }
|
|
|
+ todayData.setWarehousing(todayData.getWarehousing() + statisticsOutboundRate.getWarehousing());
|
|
|
+ todayData.setOutboundNum(todayData.getOutboundNum() + statisticsOutboundRate.getOutboundNum());
|
|
|
+ todayData.getDetailInfo().add(statisticsOutboundRate);
|
|
|
+ });
|
|
|
+ todayData.setWaitOutboundNum(todayData.getWarehousing() - todayData.getOutboundNum());
|
|
|
+ if (null != numberFormat){
|
|
|
+ if(todayData.getWarehousing() == 0){
|
|
|
+ todayData.setOutboundRate("0%");
|
|
|
+ }else {
|
|
|
+ todayData.setOutboundRate(numberFormat.format((float) todayData.getOutboundNum() / (float) todayData.getWarehousing() * 100) + "%");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return todayData;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 单个订单入库
|
|
|
* @param filter
|
|
@@ -651,7 +837,13 @@ public class DeliverysServiceImpl extends BasicsService implements DeliverysServ
|
|
|
throw new BusinessException("面单号重复");
|
|
|
}
|
|
|
if(!expressConsumeService.checkExpressBalance(filter.getStoreId(), storageDeliveryFilter.getExpId())){
|
|
|
- throw new BusinessException("快递余额不足,请联系管理员充值");
|
|
|
+ String express = CacheTool.initExpress().getString(storageDeliveryFilter.getExpId().toString());
|
|
|
+ if (StringUtils.isNotBlank(express)){
|
|
|
+ ExpressType expressCompany = JSONObject.parseObject(express, ExpressType.class);
|
|
|
+ throw new BusinessException(expressCompany.getExpName() + "快递余额不足,请联系管理员充值");
|
|
|
+ }else{
|
|
|
+ throw new BusinessException("快递余额不足,请联系管理员充值");
|
|
|
+ }
|
|
|
}
|
|
|
if (storageDeliveryFilter.getTelPhone() != null){
|
|
|
//白名单用户
|
|
@@ -682,7 +874,7 @@ public class DeliverysServiceImpl extends BasicsService implements DeliverysServ
|
|
|
try{
|
|
|
delivery = insertDelivery(store, storageDeliveryFilter, whiteUser, odeliveryType, user.getUserId());
|
|
|
}catch (Exception e){
|
|
|
- throw new BusinessException("面单号重复");
|
|
|
+ throw new BusinessException("入库失败");
|
|
|
}
|
|
|
|
|
|
//下面代码执行顺序中,手机号同步和入库签收回传调用必须在最后面,防止事务回滚却发送了签收回传和手机号同步mq
|
|
@@ -696,7 +888,7 @@ public class DeliverysServiceImpl extends BasicsService implements DeliverysServ
|
|
|
//短信自动发送开关
|
|
|
this.smsAutomaticSend(user, delivery,whiteUser);
|
|
|
//手机号同步
|
|
|
- this.phoneLibPush(store.getId(), storageDeliveryFilter.getTelPhone());
|
|
|
+ this.phoneLibPush(filter, store.getId(), storageDeliveryFilter.getTelPhone());
|
|
|
}
|
|
|
//添加订单流水记录
|
|
|
deliveryRunningWaterService.addDeliveryInsert(appVersion, apiVersion, delivery, HttpUtil.getDeviceType(), user.getUserId(),HttpUtil.getHeader("imei"));
|
|
@@ -944,12 +1136,19 @@ public class DeliverysServiceImpl extends BasicsService implements DeliverysServ
|
|
|
/**
|
|
|
* 手机号同步
|
|
|
*
|
|
|
+ * @param filter
|
|
|
* @param storeId
|
|
|
* @param phone
|
|
|
*/
|
|
|
- private void phoneLibPush(Integer storeId, String phone) {
|
|
|
+ private void phoneLibPush(DeliveryFilter filter, Integer storeId, String phone) {
|
|
|
PhoneLibDto phoneLibDto = PhoneLibDto.builder()
|
|
|
.storeId(storeId)
|
|
|
+ .consingeeName(filter.getConsingeeName())
|
|
|
+ .consingeePhone(phone.trim())
|
|
|
+ .address(filter.getAddress())
|
|
|
+ .buildingNumber(filter.getBuildingNumber())
|
|
|
+ .floorNumber(filter.getFloorNumber())
|
|
|
+ .remark(filter.getRemark())
|
|
|
.phones(phone.trim())
|
|
|
.build();
|
|
|
phoneLibDto.setCreateTime(new Date());
|