| @@ -0,0 +1,115 @@ | |||
| package com.iformall.controller.mem; | |||
| import cn.afterturn.easypoi.excel.ExcelImportUtil; | |||
| import cn.afterturn.easypoi.excel.entity.ImportParams; | |||
| import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult; | |||
| import cn.afterturn.easypoi.handler.impl.ExcelDataHandlerDefaultImpl; | |||
| import cn.afterturn.easypoi.handler.inter.IExcelDataHandler; | |||
| import com.iformall.domain.po.MallUserInfo; | |||
| import com.iformall.domain.vo.WxBillDailyVo; | |||
| import com.iformall.service.WxBillDailyService; | |||
| import org.apache.shiro.session.UnknownSessionException; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.data.redis.core.StringRedisTemplate; | |||
| import org.springframework.scheduling.annotation.Async; | |||
| import org.springframework.stereotype.Component; | |||
| import java.io.File; | |||
| import java.util.List; | |||
| import java.util.concurrent.TimeUnit; | |||
| @Component | |||
| public class BillDailyAsyncTask { | |||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||
| @Autowired | |||
| private WxBillDailyService wxBillDailyService; | |||
| @Autowired | |||
| StringRedisTemplate stringRedisTemplate; | |||
| private class BillDailyExcelHandler extends ExcelDataHandlerDefaultImpl<WxBillDailyVo> { | |||
| @Override | |||
| public Object importHandler(WxBillDailyVo obj, String name, Object value) { | |||
| if (value == null) { | |||
| value = ""; | |||
| } | |||
| System.out.println(name + " + " + value.toString()); | |||
| return super.importHandler(obj, name, value); | |||
| } | |||
| } | |||
| private void set_redis_value(String importKey, String allCount, String allSuccessCount, String processCount, String failCount, boolean fail) { | |||
| stringRedisTemplate.opsForHash().put(importKey, "allCount", allCount); | |||
| stringRedisTemplate.opsForHash().put(importKey, "allSuccessCount", allSuccessCount); | |||
| stringRedisTemplate.opsForHash().put(importKey, "processCount", processCount); | |||
| stringRedisTemplate.opsForHash().put(importKey, "failCount", failCount); | |||
| if (fail) { | |||
| stringRedisTemplate.expire(importKey, 10, TimeUnit.SECONDS); | |||
| } | |||
| } | |||
| @Async | |||
| public void importExcelData(File file, MallUserInfo user, String importKey, String tenantId) { | |||
| ImportParams params = new ImportParams(); | |||
| // 需要验证 | |||
| params.setImportFields(new String[]{"商铺号", "费用类型", "实际应收金额", "实收金额", "欠缴金额", "截止收款日期", "逾期天数"}); | |||
| IExcelDataHandler<WxBillDailyVo> handler = new BillDailyAsyncTask.BillDailyExcelHandler(); | |||
| handler.setNeedHandlerFields(new String[]{"商铺号", "费用类型", "实际应收金额", "实收金额", "欠缴金额", "截止收款日期", "逾期天数"}); | |||
| params.setNeedVerify(true); | |||
| ExcelImportResult<WxBillDailyVo> datalist = null; | |||
| try { | |||
| datalist = ExcelImportUtil.importExcelMore(file, WxBillDailyVo.class, params); | |||
| } catch (Exception e) { | |||
| set_redis_value(importKey, "1", "0", "0", "1", true); | |||
| logger.error(e.getMessage()); | |||
| // 删除缓存文件 | |||
| file.delete(); | |||
| return; | |||
| } | |||
| // 删除缓存文件 | |||
| file.delete(); | |||
| if (datalist == null) { | |||
| logger.error("导入模板失败: 模板数据解析失败"); | |||
| set_redis_value(importKey, "1", "0", "0", "1", true); | |||
| return; | |||
| } | |||
| List<WxBillDailyVo> successList = datalist.getList(); | |||
| List<WxBillDailyVo> failList = datalist.getFailList(); | |||
| logger.info("验证通过的数量: " + successList.size()); | |||
| logger.info("验证未通过的数量: " + failList.size()); | |||
| int total = successList.size() + failList.size(); | |||
| int all_success = successList.size(); | |||
| int all_fail = failList.size(); | |||
| //添加到redis里 | |||
| set_redis_value(importKey, "" + total, "" + all_success, "0", "" + all_fail, total == all_fail); | |||
| if (successList.size() > 0) { | |||
| try { | |||
| successList.parallelStream().forEach(billDaily -> { | |||
| try { | |||
| //插入数据 | |||
| billDaily.setTenantId(tenantId); | |||
| wxBillDailyService.insertData(billDaily, importKey, user); | |||
| } catch (UnknownSessionException ue) { | |||
| logger.error("session :" + ue.getMessage()); | |||
| } | |||
| }); | |||
| } catch (Exception e) { | |||
| set_redis_value(importKey, "1", "0", "0", "1", true); | |||
| e.printStackTrace(); | |||
| logger.error("导入模板失败:" + e.getMessage()); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -2,22 +2,33 @@ package com.iformall.controller.rent; | |||
| import com.github.pagehelper.PageInfo; | |||
| import com.iformall.annotation.SystemControllerLog; | |||
| import com.iformall.common.ErrorCode; | |||
| import com.iformall.common.Result; | |||
| import com.iformall.common.ResultData; | |||
| import com.iformall.controller.base.BaseController; | |||
| import com.iformall.controller.mem.BillDailyAsyncTask; | |||
| import com.iformall.domain.po.MallUserInfo; | |||
| import com.iformall.domain.po.WxBillDaily; | |||
| import com.iformall.exception.MallinkException; | |||
| import com.iformall.service.WxBillDailyService; | |||
| import com.iformall.utils.Constant; | |||
| import io.swagger.annotations.ApiImplicitParam; | |||
| import io.swagger.annotations.ApiImplicitParams; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.data.redis.core.StringRedisTemplate; | |||
| import org.springframework.web.bind.annotation.*; | |||
| import org.springframework.web.multipart.MultipartFile; | |||
| import javax.servlet.http.HttpServletRequest; | |||
| import javax.servlet.http.HttpServletResponse; | |||
| import java.io.BufferedInputStream; | |||
| import java.io.File; | |||
| import java.io.FileOutputStream; | |||
| import java.io.IOException; | |||
| import java.util.Map; | |||
| import java.util.concurrent.TimeUnit; | |||
| /** | |||
| * @author gongbiao | |||
| @@ -28,6 +39,12 @@ public class WxBillDailyController extends BaseController { | |||
| @Autowired | |||
| private WxBillDailyService wxBillDailyService; | |||
| @Autowired | |||
| StringRedisTemplate stringRedisTemplate; | |||
| @Autowired | |||
| private BillDailyAsyncTask billDailyAsyncTask; | |||
| private Logger logger = LoggerFactory.getLogger(this.getClass()); | |||
| @GetMapping("list") | |||
| @@ -97,4 +114,88 @@ public class WxBillDailyController extends BaseController { | |||
| } | |||
| @PostMapping(value = "/importTemplate", consumes = "multipart/*") | |||
| @SystemControllerLog(description = "会员管理-导入数据") | |||
| public ResultData importTemplate(@RequestParam("file") MultipartFile mFile) { | |||
| logger.debug("[" + getIpAddr() + "] WxCUserBasicInfoController::importTemplate"); | |||
| if (mFile.isEmpty()) { | |||
| throw new MallinkException(Result.ERROR, "上传文件不能为空"); | |||
| } | |||
| //得到当前用户ID | |||
| final MallUserInfo user = getUser(); | |||
| String userId = "bill_daily_" + user.getId(); | |||
| String importKey = Constant.importMemPrev + userId; | |||
| final String tenantId = getTenantId(); | |||
| //查询当前用户得到的值是否为空,为空继续,不为空,返回模板正在导入 | |||
| Boolean allCount = stringRedisTemplate.opsForHash().hasKey(importKey, "allCount"); | |||
| if (allCount) { | |||
| return new ResultData(Result.SUCCESS, "模板正在导入"); | |||
| } | |||
| stringRedisTemplate.opsForHash().putIfAbsent(importKey, "allCount", 0 + ""); | |||
| stringRedisTemplate.expire(importKey, 30, TimeUnit.MINUTES); | |||
| stringRedisTemplate.opsForHash().putIfAbsent(importKey, "allSuccessCount", 0 + ""); | |||
| stringRedisTemplate.opsForHash().putIfAbsent(importKey, "processCount", ""); | |||
| stringRedisTemplate.opsForHash().putIfAbsent(importKey, "failCount", ""); | |||
| String fpath = Constant.fileDirectory; | |||
| File targetFile = new File(fpath); | |||
| if (!targetFile.exists()) { | |||
| targetFile.mkdirs(); | |||
| } | |||
| String fileName = "bill_daily.xls"; | |||
| int dot = mFile.getOriginalFilename().lastIndexOf('.'); | |||
| fileName = fileName + mFile.getOriginalFilename().substring(dot, mFile.getOriginalFilename().length()); | |||
| File lFile = new File(fpath + File.separator + fileName); | |||
| FileOutputStream fos = null; | |||
| BufferedInputStream fs = null; | |||
| try { | |||
| fos = new FileOutputStream(lFile); | |||
| fs = (BufferedInputStream) mFile.getInputStream(); | |||
| byte[] buffer = new byte[1024]; | |||
| int len = 0; | |||
| while ((len = fs.read(buffer)) != -1) { | |||
| fos.write(buffer, 0, len); | |||
| } | |||
| fos.close(); | |||
| fs.close(); | |||
| } catch (Exception e) { | |||
| stringRedisTemplate.expire(importKey, 3, TimeUnit.SECONDS); | |||
| stringRedisTemplate.opsForHash().putIfAbsent(importKey, "allCount", "1"); | |||
| stringRedisTemplate.opsForHash().putIfAbsent(importKey, "failCount", "1"); | |||
| logger.error(e.getMessage()); | |||
| return new ResultData(ErrorCode.MEM_IMPORT_ERR.getCode(), "模板上传失败"); | |||
| } finally { | |||
| if (fos != null) { | |||
| try { | |||
| fos.close(); | |||
| } catch (IOException e) { | |||
| stringRedisTemplate.expire(importKey, 3, TimeUnit.SECONDS); | |||
| stringRedisTemplate.opsForHash().putIfAbsent(importKey, "allCount", "1"); | |||
| stringRedisTemplate.opsForHash().putIfAbsent(importKey, "failCount", "1"); | |||
| logger.error(e.getMessage()); | |||
| return new ResultData(ErrorCode.MEM_IMPORT_ERR.getCode(), "模板上传失败"); | |||
| } | |||
| } | |||
| if (fs != null) { | |||
| try { | |||
| fs.close(); | |||
| } catch (IOException e) { | |||
| stringRedisTemplate.expire(importKey, 3, TimeUnit.SECONDS); | |||
| stringRedisTemplate.opsForHash().putIfAbsent(importKey, "allCount", "1"); | |||
| stringRedisTemplate.opsForHash().putIfAbsent(importKey, "failCount", "1"); | |||
| logger.error(e.getMessage()); | |||
| return new ResultData(ErrorCode.MEM_IMPORT_ERR.getCode(), "模板上传失败"); | |||
| } | |||
| } | |||
| } | |||
| billDailyAsyncTask.importExcelData(lFile, user, importKey, tenantId); | |||
| return new ResultData(Result.SUCCESS, "模板正在导入"); | |||
| } | |||
| } | |||
| @@ -6,6 +6,9 @@ import com.iformall.domain.po.WxBillDaily; | |||
| import javax.validation.constraints.NotNull; | |||
| /** | |||
| * @author gongbiao | |||
| */ | |||
| public class WxBillDailyVo extends WxBillDaily { | |||
| @Excel(name = "商铺号", width = 20, orderNum = "1") | |||
| @@ -4,6 +4,7 @@ import com.github.pagehelper.PageInfo; | |||
| import com.iformall.common.ResultData; | |||
| import com.iformall.domain.po.MallUserInfo; | |||
| import com.iformall.domain.po.WxBillDaily; | |||
| import com.iformall.domain.vo.WxBillDailyVo; | |||
| import javax.servlet.http.HttpServletRequest; | |||
| import javax.servlet.http.HttpServletResponse; | |||
| @@ -54,4 +55,6 @@ public interface WxBillDailyService { | |||
| void exportTemplate(HttpServletRequest request, HttpServletResponse response, String tenantId); | |||
| void insertData(WxBillDailyVo billDaily, String importKey, MallUserInfo user); | |||
| } | |||
| @@ -6,21 +6,22 @@ import com.iformall.common.ErrorCode; | |||
| import com.iformall.common.IdWorker; | |||
| import com.iformall.common.Result; | |||
| import com.iformall.common.ResultData; | |||
| import com.iformall.domain.po.MallUserInfo; | |||
| import com.iformall.domain.po.WxBillAction; | |||
| import com.iformall.domain.po.WxBillDaily; | |||
| import com.iformall.domain.po.WxShop; | |||
| import com.iformall.domain.po.*; | |||
| import com.iformall.domain.vo.WxBillDailyVo; | |||
| import com.iformall.enums.*; | |||
| import com.iformall.exception.MallinkException; | |||
| import com.iformall.mapper.WxBillDailyMapper; | |||
| import com.iformall.mapper.WxMerchantShopMapper; | |||
| import com.iformall.mapper.WxShopMapper; | |||
| import com.iformall.service.ExcelService; | |||
| import com.iformall.service.WxBillActionService; | |||
| import com.iformall.service.WxBillDailyService; | |||
| import com.iformall.utils.DateUtils; | |||
| import org.apache.commons.lang3.StringUtils; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.data.redis.core.StringRedisTemplate; | |||
| import org.springframework.stereotype.Service; | |||
| import org.springframework.transaction.annotation.Transactional; | |||
| @@ -28,6 +29,7 @@ import javax.servlet.http.HttpServletRequest; | |||
| import javax.servlet.http.HttpServletResponse; | |||
| import java.math.BigDecimal; | |||
| import java.util.*; | |||
| import java.util.concurrent.TimeUnit; | |||
| /** | |||
| * @author gongbiao | |||
| @@ -45,6 +47,10 @@ public class WxBillDailyServiceImpl implements WxBillDailyService { | |||
| WxBillActionService wxBillActionService; | |||
| @Autowired | |||
| ExcelService excelService; | |||
| @Autowired | |||
| StringRedisTemplate stringRedisTemplate; | |||
| @Autowired | |||
| WxMerchantShopMapper wxMerchantShopMapper; | |||
| @Override | |||
| public PageInfo<Map<String, Object>> listAsPage(WxBillDaily record, Integer pageIndex, Integer pageSize) { | |||
| //更新账单状态 | |||
| @@ -236,5 +242,104 @@ public class WxBillDailyServiceImpl implements WxBillDailyService { | |||
| } | |||
| @Override | |||
| public void insertData(WxBillDailyVo billDaily, String importKey, MallUserInfo user) { | |||
| String shopNumber = billDaily.getShopNumber(); | |||
| if (StringUtils.isBlank(shopNumber)) { | |||
| stringRedisTemplate.opsForHash().increment(importKey, "processCount", 1); | |||
| logger.error("商铺号为空", billDaily.toString()); | |||
| return; | |||
| } | |||
| //店铺 | |||
| WxShop shop = new WxShop(); | |||
| shop.setShopNumber(shopNumber); | |||
| shop.setTenantId(billDaily.getTenantId()); | |||
| shop.setStatus(EnumShopStatus.RENT.getCode()); | |||
| shop.setIsDel(EnumDelStatus.NOT_DEL.getCode()); | |||
| WxShop wxShop = wxShopMapper.selectOne(shop); | |||
| if (wxShop == null) { | |||
| stringRedisTemplate.opsForHash().increment(importKey, "processCount", 1); | |||
| logger.error("商铺未找到", billDaily.toString()); | |||
| return; | |||
| } | |||
| Integer type = billDaily.getType(); | |||
| if (type != null && (type.equals(EnumBillDailyType.WATER.getCode()) || type.equals(EnumBillDailyType.POWER.getCode()))) { | |||
| stringRedisTemplate.opsForHash().increment(importKey, "processCount", 1); | |||
| logger.error("账单类型为空", billDaily.toString()); | |||
| return; | |||
| } | |||
| String receivePayStr = billDaily.getReceivePayStr(); | |||
| if (StringUtils.isBlank(receivePayStr)) { | |||
| stringRedisTemplate.opsForHash().increment(importKey, "processCount", 1); | |||
| logger.error("实际应收金额为空", billDaily.toString()); | |||
| return; | |||
| } | |||
| double receivePayD = new BigDecimal(receivePayStr).doubleValue(); | |||
| if (receivePayD <= 0) { | |||
| stringRedisTemplate.opsForHash().increment(importKey, "processCount", 1); | |||
| logger.error("实际应收金额小于等于0", billDaily.toString()); | |||
| return; | |||
| } | |||
| String payStr = billDaily.getPayStr(); | |||
| if (StringUtils.isBlank(payStr)) { | |||
| stringRedisTemplate.opsForHash().increment(importKey, "processCount", 1); | |||
| logger.error("实收金额为空", billDaily.toString()); | |||
| return; | |||
| } | |||
| double payD = new BigDecimal(payStr).doubleValue(); | |||
| if (payD < 0) { | |||
| stringRedisTemplate.opsForHash().increment(importKey, "processCount", 1); | |||
| logger.error("实收金额小于0", billDaily.toString()); | |||
| return; | |||
| } | |||
| String oweStr = billDaily.getOweStr(); | |||
| if (StringUtils.isBlank(oweStr)) { | |||
| stringRedisTemplate.opsForHash().increment(importKey, "processCount", 1); | |||
| logger.error("欠缴金额为空", billDaily.toString()); | |||
| return; | |||
| } | |||
| double oweD = new BigDecimal(oweStr).doubleValue(); | |||
| if (oweD < 0) { | |||
| stringRedisTemplate.opsForHash().increment(importKey, "processCount", 1); | |||
| logger.error("欠缴金额小于0", billDaily.toString()); | |||
| return; | |||
| } | |||
| long owe = new BigDecimal(oweD).multiply(new BigDecimal(100)).longValue(); | |||
| billDaily.setOwe(owe); | |||
| Date receiveDate = billDaily.getReceiveDate(); | |||
| Date date = new Date(); | |||
| int expiredDay = DateUtils.daysBetween(receiveDate, date); | |||
| billDaily.setExpiredDay((long) expiredDay); | |||
| if (expiredDay > 0) { | |||
| billDaily.setStatus(EnumBillRentStatus.NOT_PAID.getCode()); | |||
| } else { | |||
| billDaily.setStatus(EnumBillRentStatus.WAIT_PAY.getCode()); | |||
| } | |||
| if (receivePayD == payD) { | |||
| billDaily.setStatus(EnumBillRentStatus.PAID.getCode()); | |||
| } | |||
| billDaily.setShopId(wxShop.getId()); | |||
| billDaily.setRentShopType(wxShop.getType()); | |||
| billDaily.setPayWay(EnumBillPayWay.OTHER.getCode()); | |||
| billDaily.setCreatetime(date); | |||
| billDaily.setUpdatetime(date); | |||
| //商户 | |||
| WxMerchantShop merchantShop = new WxMerchantShop(); | |||
| merchantShop.setShopId(wxShop.getId()); | |||
| merchantShop.setIsDel(EnumDelStatus.NOT_DEL.getCode()); | |||
| WxMerchantShop wxMerchantShop = wxMerchantShopMapper.selectOne(merchantShop); | |||
| billDaily.setMerchantId(wxMerchantShop.getMerchantId()); | |||
| final IdWorker idWorker = IdWorker.get(); | |||
| billDaily.setId(idWorker.nextId()); | |||
| wxBillDailyMapper.insertSelective(billDaily); | |||
| //记数 | |||
| stringRedisTemplate.opsForHash().increment(importKey, "processCount", 1); | |||
| stringRedisTemplate.expire(importKey, 10, TimeUnit.SECONDS); | |||
| } | |||
| } | |||