| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.doumee.service.business.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.doumee.core.constants.Constants; |
| | | import com.doumee.core.constants.ResponseStatus; |
| | | import com.doumee.core.exception.BusinessException; |
| | | import com.doumee.core.model.PageData; |
| | | import com.doumee.core.model.PageWrap; |
| | | import com.doumee.core.utils.DateUtil; |
| | | import com.doumee.dao.business.BaseParamMapper; |
| | | import com.doumee.dao.business.BikesMapper; |
| | | import com.doumee.dao.business.GoodsorderMapper; |
| | | import com.doumee.dao.business.MemberMapper; |
| | | import com.doumee.dao.business.MemberRidesTrackMapper; |
| | | import com.doumee.dao.business.join.MemberRidesJoinMapper; |
| | | import com.doumee.dao.business.model.BaseParam; |
| | | import com.doumee.dao.business.model.Bikes; |
| | | import com.doumee.dao.business.model.Goodsorder; |
| | | import com.doumee.dao.business.model.Member; |
| | | import com.doumee.dao.business.model.MemberRides; |
| | | import com.doumee.dao.business.model.MemberRidesTrack; |
| | | import com.doumee.dao.business.vo.BikeIncomeStatVO; |
| | | import com.doumee.dao.business.vo.BikeUsageStatVO; |
| | | import com.doumee.dao.business.vo.DashboardVO; |
| | | import com.doumee.dao.business.vo.IncomeDailyVO; |
| | | import com.doumee.dao.business.vo.IncomeStatVO; |
| | | import com.doumee.dao.business.vo.OperationCenterVO; |
| | | import com.doumee.dao.business.vo.OperationOrderVO; |
| | | import com.doumee.dao.business.vo.OrderRideItemVO; |
| | | import com.doumee.dao.business.vo.OrderRideTrackVO; |
| | | import com.doumee.dao.business.vo.OrderRidesDetailVO; |
| | | import com.doumee.dao.business.vo.OverviewStatVO; |
| | | import com.doumee.dao.business.vo.PackageSourceStatVO; |
| | | import com.doumee.dao.business.web.request.BikeIncomeQueryDTO; |
| | | import com.doumee.dao.business.web.request.OperationOrderQueryDTO; |
| | | import com.doumee.service.business.ReportService; |
| | | import com.github.yulichang.wrapper.MPJLambdaWrapper; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.ArrayList; |
| | | import java.util.Calendar; |
| | | import java.util.Collections; |
| | | import java.util.Comparator; |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Objects; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * æ°æ®æ¥è¡¨ Service å®ç°(web 端:æ¦è§ç»è®¡ + æ¶å
¥è½¦ååæ)ã |
| | | * |
| | | * @author rk |
| | | * @date 2026/06/26 |
| | | */ |
| | | @Slf4j |
| | | @Service |
| | | public class ReportServiceImpl implements ReportService { |
| | | |
| | | @Autowired |
| | | private MemberMapper memberMapper; |
| | | @Autowired |
| | | private MemberRidesJoinMapper memberRidesJoinMapper; |
| | | @Autowired |
| | | private BikesMapper bikesMapper; |
| | | @Autowired |
| | | private GoodsorderMapper goodsorderMapper; |
| | | @Autowired |
| | | private BaseParamMapper baseParamMapper; |
| | | /** çµè½¦éªè¡è½¨è¿¹ Mapper(èªè¡è½¦èµ° MQTT æ 轨迹,ä»
çµè½¦ææ°æ®) */ |
| | | @Autowired |
| | | private MemberRidesTrackMapper memberRidesTrackMapper; |
| | | |
| | | /** æ¶æ®µå¿«æ·ç±»å â è¿ N 天:dateType 1â7ã2â15ã3â30(åå«ä»å¤©) */ |
| | | private static final Map<Integer, Integer> RECENT_DAYS = new LinkedHashMap<>(); |
| | | |
| | | static { |
| | | RECENT_DAYS.put(1, 7); |
| | | RECENT_DAYS.put(2, 15); |
| | | RECENT_DAYS.put(3, 30); |
| | | } |
| | | |
| | | /** ç»ç®éé¢åâå
æ¢ç®é¤æ° */ |
| | | private static final BigDecimal CENT_PER_YUAN = new BigDecimal("100"); |
| | | |
| | | /** ç¾åæ¯åºæ°(å¢é¿ç = (æ¬æ - å¯¹æ¯æ) / å¯¹æ¯æ à 100) */ |
| | | private static final BigDecimal PERCENT_BASE = new BigDecimal("100"); |
| | | |
| | | /** æ¯ä»æ¹å¼:æé³å¸æ ¸é(å¥é¤é宿¥æºè¯å«ç¨) */ |
| | | private static final int PAY_WAY_DOUYIN = 2; |
| | | |
| | | @Override |
| | | public OverviewStatVO overview() { |
| | | OverviewStatVO vo = new OverviewStatVO(); |
| | | // æ»æ³¨åç¨æ·:æªå é¤çå
¨é¨ç¨æ· |
| | | vo.setTotalMembers((long) memberMapper.selectCount( |
| | | new QueryWrapper<Member>().lambda().eq(Member::getIsdeleted, Constants.ZERO))); |
| | | // 仿¥æ°å¢:å建æ¶é´ â¥ ä»æ¥0ç¹ |
| | | Date todayStart = DateUtil.getStartOfDay(new Date()); |
| | | vo.setTodayMembers((long) memberMapper.selectCount( |
| | | new QueryWrapper<Member>().lambda() |
| | | .eq(Member::getIsdeleted, Constants.ZERO) |
| | | .ge(Member::getCreateDate, todayStart))); |
| | | // èªè¡è½¦æ°é(type=0),çµå¨è½¦æ°é(type=1);åå«å
¨é¨æªå é¤è½¦è¾(å«ç¦ç¨) |
| | | vo.setBikeCount((long) bikesMapper.selectCount( |
| | | new QueryWrapper<Bikes>().lambda() |
| | | .eq(Bikes::getType, Constants.ZERO) |
| | | .eq(Bikes::getIsdeleted, Constants.ZERO))); |
| | | vo.setEleBikeCount((long) bikesMapper.selectCount( |
| | | new QueryWrapper<Bikes>().lambda() |
| | | .eq(Bikes::getType, Constants.ONE) |
| | | .eq(Bikes::getIsdeleted, Constants.ZERO))); |
| | | return vo; |
| | | } |
| | | |
| | | @Override |
| | | public List<BikeIncomeStatVO> bikeIncome(BikeIncomeQueryDTO query) { |
| | | // 1. è§£ææ¶æ®µ:1/2/3 è¿ N 天(å«ä»å¤©å
± N 天),4 èªå®ä¹ |
| | | DateRange range = resolveRange(query); |
| | | Date start = range.start; |
| | | Date end = range.end; |
| | | |
| | | // 2. 车ååå
¸:base_param type=3 å车 / 4 çµè½¦,ä¾è½¦åå + 大类å½ç±» |
| | | List<BaseParam> paramList = baseParamMapper.selectList( |
| | | new QueryWrapper<BaseParam>().lambda() |
| | | .eq(BaseParam::getIsdeleted, Constants.ZERO) |
| | | .in(BaseParam::getType, Constants.THREE, Constants.FOUR)); |
| | | Map<String, BaseParam> paramMap = paramList.stream() |
| | | .collect(Collectors.toMap(BaseParam::getId, p -> p, (a, b) -> a)); |
| | | |
| | | // 3. æ¶æ®µå
å·²ç»ç®çç§è½¦æ¼é订å(æ¥è¯¢æ¨¡å¼åèåå° getBikeIncomeReportVOList: |
| | | // type=0 æ¼éç±»ãstatus=4 å·²ç»ç®ãparamId é空ãpayDate è½å¨åºé´å
) |
| | | List<Goodsorder> orders = goodsorderMapper.selectList( |
| | | new QueryWrapper<Goodsorder>().lambda() |
| | | .eq(Goodsorder::getType, Constants.ZERO) |
| | | .eq(Goodsorder::getStatus, Constants.FOUR) |
| | | .eq(Goodsorder::getIsdeleted, Constants.ZERO) |
| | | .isNotNull(Goodsorder::getParamId) |
| | | .ne(Goodsorder::getParamId, StringUtils.EMPTY) |
| | | .ge(Goodsorder::getPayDate, start) |
| | | .le(Goodsorder::getPayDate, end)); |
| | | |
| | | // 4. æ paramId(车å)åç»å计ç»ç®éé¢ closeMoney(åä½:å) |
| | | Map<String, BigDecimal> incomeByParam = new LinkedHashMap<>(); |
| | | for (Goodsorder o : orders) { |
| | | BigDecimal amount = o.getCloseMoney() == null ? BigDecimal.ZERO : o.getCloseMoney(); |
| | | incomeByParam.merge(o.getParamId(), amount, BigDecimal::add); |
| | | } |
| | | |
| | | // 5. ç»è£
ç»æ:车åå + 大类 + æ¶å
¥(åâå
,2ä½),ææ¶å
¥éåº |
| | | List<BikeIncomeStatVO> result = new ArrayList<>(); |
| | | for (Map.Entry<String, BigDecimal> e : incomeByParam.entrySet()) { |
| | | BaseParam param = paramMap.get(e.getKey()); |
| | | BikeIncomeStatVO vo = new BikeIncomeStatVO(); |
| | | vo.setParamId(e.getKey()); |
| | | vo.setParamName(param == null ? "æªç¥è½¦å" : param.getName()); |
| | | vo.setCategory(param == null ? "æªç¥" : categoryOf(param.getType())); |
| | | vo.setIncome(e.getValue().divide(CENT_PER_YUAN, 2, BigDecimal.ROUND_HALF_UP)); |
| | | result.add(vo); |
| | | } |
| | | result.sort(Comparator.comparing(BikeIncomeStatVO::getIncome).reversed()); |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * æ base_param.type æ´¾ç车è¾å¤§ç±»:3 èªè¡è½¦ / 4 çµå¨è½¦,å
¶ä½å½"æªç¥"ã |
| | | * |
| | | * @param type base_param.type(3 å车类å / 4 çµè½¦ç±»å) |
| | | * @return å¤§ç±»ä¸æå |
| | | */ |
| | | private String categoryOf(Integer type) { |
| | | if (type == null) { |
| | | return "æªç¥"; |
| | | } |
| | | // 注æ:Constants.THREE æ¯ IntegerãConstants.FOUR æ¯ int(ç±»åä¸ä¸è´), |
| | | // ç»ä¸ææ int æ¯è¾,é¿å¼å¯¹åºæ¬ç±»åè°ç¨ equals / å
è£
ç±»å¼ç¨æ¯è¾çå |
| | | int t = type; |
| | | if (t == Constants.THREE) { |
| | | return "èªè¡è½¦"; |
| | | } |
| | | if (t == Constants.FOUR) { |
| | | return "çµå¨è½¦"; |
| | | } |
| | | return "æªç¥"; |
| | | } |
| | | |
| | | /** |
| | | * è§£æåçæ¥è¯¢æ¶æ®µ(åå«ç«¯ç¹)ã |
| | | */ |
| | | private static final class DateRange { |
| | | /** èµ·å§æ¶é´(å«) */ |
| | | final Date start; |
| | | /** ç»ææ¶é´(å«) */ |
| | | final Date end; |
| | | |
| | | DateRange(Date start, Date end) { |
| | | this.start = start; |
| | | this.end = end; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è§£ææ¥è¯¢æ¶æ®µ:dateType 1/2/3 â è¿ N 天(å«ä»å¤©å
± N 天),4 â èªå®ä¹èµ·æ¢(åå«)ã |
| | | * <p>{@link #bikeIncome} ä¸ {@link #incomeStat} å
±ç¨,ä¿è¯ä¸¤ç«¯æ¶æ®µå£å¾ä¸è´ã |
| | | * |
| | | * @param query æ¶æ®µæ¥è¯¢å
¥å |
| | | * @return è§£æåç [start, end] åºé´ |
| | | */ |
| | | private DateRange resolveRange(BikeIncomeQueryDTO query) { |
| | | if (query == null) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST); |
| | | } |
| | | Integer dateType = query.getDateType(); |
| | | Date start; |
| | | Date end; |
| | | if (dateType != null && RECENT_DAYS.containsKey(dateType)) { |
| | | // å¿«æ·:è¿ N 天,å«ä»å¤©å
± N 天,èµ·å§ = ä»å¤©å¾å N-1 天ç0ç¹ |
| | | int days = RECENT_DAYS.get(dateType); |
| | | end = DateUtil.getEndOfDay(new Date()); |
| | | start = DateUtil.getStartOfDay(DateUtil.increaseDay(new Date(), -(days - 1))); |
| | | } else if (dateType != null && dateType == 4) { |
| | | // èªå®ä¹:èµ·æ¢åå«,æ ¡éªéç©ºä¸ start<=end |
| | | if (query.getStartDate() == null || query.getEndDate() == null |
| | | || query.getStartDate().getTime() > query.getEndDate().getTime()) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "èªå®ä¹æ¶æ®µèµ·æ¢æ¥æä¸åæ³"); |
| | | } |
| | | start = query.getStartDate(); |
| | | end = query.getEndDate(); |
| | | } else { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "æ¶æ®µç±»åä¸åæ³"); |
| | | } |
| | | return new DateRange(start, end); |
| | | } |
| | | |
| | | @Override |
| | | public IncomeStatVO incomeStat(BikeIncomeQueryDTO query) { |
| | | // 1. è§£ææ¶æ®µ |
| | | DateRange range = resolveRange(query); |
| | | Date start = range.start; |
| | | Date end = range.end; |
| | | |
| | | // 2. æ¥è¯¢æ¬æå·²ç»ç®çç§è½¦æ¼é订å(æ¥è¯¢æ¨¡å¼åèåå° getTotalData / getBikeIncomeReportVOList: |
| | | // type=0 æ¼éç±»ãstatus=4 å·²ç»ç®ãpayDate è½å¨åºé´å
)ãæ¶å
¥ç»è®¡ä¸é车å,æ
ä¸çº¦æ paramId |
| | | List<Goodsorder> orders = goodsorderMapper.selectList( |
| | | new QueryWrapper<Goodsorder>().lambda() |
| | | .eq(Goodsorder::getType, Constants.ZERO) |
| | | .eq(Goodsorder::getStatus, Constants.FOUR) |
| | | .eq(Goodsorder::getIsdeleted, Constants.ZERO) |
| | | .ge(Goodsorder::getPayDate, start) |
| | | .le(Goodsorder::getPayDate, end)); |
| | | |
| | | // 3. æ payDate çæ¥æ(yyyy-MM-dd)åç»æ±æ» closeMoney(åä½:å),åæ¶ç´¯è®¡åºé´æ»é¢ |
| | | Map<String, BigDecimal> sumByDay = new LinkedHashMap<>(); |
| | | BigDecimal totalCents = BigDecimal.ZERO; |
| | | for (Goodsorder o : orders) { |
| | | BigDecimal amount = o.getCloseMoney() == null ? BigDecimal.ZERO : o.getCloseMoney(); |
| | | sumByDay.merge(DateUtil.getShortDateStr(o.getPayDate()), amount, BigDecimal::add); |
| | | totalCents = totalCents.add(amount); |
| | | } |
| | | |
| | | // 4. çæå®æ´æ¥æåºå(æ±ç¶å¾æ¨ªè½´è¿ç»),æ æ°æ®æ¥è¡¥ 0ã |
| | | // 注:DateUtil.getDateList ç¨ dEnd.after(begin) æ¯è¾,è¥ä¸¤ç«¯æ¶åç§ä¸ä¸è´ä¼å¤ç®ä¸å¤©, |
| | | // æ
ç»ä¸è§æ´å°å½å¤© 0 ç¹åçæåºå |
| | | List<IncomeDailyVO> dailyList = new ArrayList<>(); |
| | | for (Date d : DateUtil.getDateList(DateUtil.getStartOfDay(start), DateUtil.getStartOfDay(end))) { |
| | | IncomeDailyVO vo = new IncomeDailyVO(); |
| | | vo.setDate(DateUtil.getShortDateStr(d)); |
| | | BigDecimal daySum = sumByDay.getOrDefault(vo.getDate(), BigDecimal.ZERO); |
| | | // åâå
,2ä½å°æ° |
| | | vo.setIncome(daySum.divide(CENT_PER_YUAN, 2, BigDecimal.ROUND_HALF_UP)); |
| | | dailyList.add(vo); |
| | | } |
| | | |
| | | // 5. åºé´ç´¯è®¡æ¶å
¥(å¤ç¨å·²æ¥çæ¬ææ°æ®,åâå
,é¿å
é夿¥è¯¢) |
| | | BigDecimal totalIncome = totalCents.divide(CENT_PER_YUAN, 2, BigDecimal.ROUND_HALF_UP); |
| | | IncomeStatVO result = new IncomeStatVO(); |
| | | result.setDailyList(dailyList); |
| | | result.setTotalIncome(totalIncome); |
| | | |
| | | // 6. ç¯æ¯:ç´§é»åä¸çé¿åºé´(æ´ä½å¹³ç§» -N 天,N=åºé´å¤©æ°)ãå¯¹æ¯æåªæ±æ»éé¢,ä¸éæ¯æ¥æç» |
| | | int spanDays = DateUtil.daysBetweenDates(start, end) + 1; |
| | | BigDecimal chainAmount = sumClosedMoney( |
| | | DateUtil.increaseDay(start, -spanDays), DateUtil.increaseDay(end, -spanDays)); |
| | | result.setChainAmount(chainAmount); |
| | | result.setChainRate(growthRate(totalIncome, chainAmount)); |
| | | |
| | | // 7. 忝:å»å¹´åæåé¿åº¦åºé´(平移 -1 å¹´,increaseYear æ Calendar 精确平移,é°å¹´ä¸å¤±ç) |
| | | BigDecimal yearOnYearAmount = sumClosedMoney( |
| | | DateUtil.increaseYear(start, -1), DateUtil.increaseYear(end, -1)); |
| | | result.setYearOnYearAmount(yearOnYearAmount); |
| | | result.setYearOnYearRate(growthRate(totalIncome, yearOnYearAmount)); |
| | | |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * æ±æ»æå®æ¶æ®µå
å·²ç»ç®ç§è½¦æ¼é订åçç»ç®æ¶å
¥(closeMoney ä¹å,åâå
)ã |
| | | * <p>ä¾ç´¯è®¡æ¶å
¥ãç¯æ¯ã忝å¤ç¨,ç»ä¸æ¶å
¥å£å¾;åª select closeMoney å以åå°æ°æ®ä¼ è¾ã |
| | | * |
| | | * @param start èµ·å§æ¶é´(å«) |
| | | * @param end ç»ææ¶é´(å«) |
| | | * @return åºé´ç»ç®æ¶å
¥(å
,2ä½å°æ°);æ æ°æ®è¿å 0 |
| | | */ |
| | | private BigDecimal sumClosedMoney(Date start, Date end) { |
| | | List<Goodsorder> orders = goodsorderMapper.selectList( |
| | | new QueryWrapper<Goodsorder>().lambda() |
| | | .select(Goodsorder::getCloseMoney) |
| | | .eq(Goodsorder::getType, Constants.ZERO) |
| | | .eq(Goodsorder::getStatus, Constants.FOUR) |
| | | .eq(Goodsorder::getIsdeleted, Constants.ZERO) |
| | | .ge(Goodsorder::getPayDate, start) |
| | | .le(Goodsorder::getPayDate, end)); |
| | | BigDecimal sum = BigDecimal.ZERO; |
| | | for (Goodsorder o : orders) { |
| | | if (o.getCloseMoney() != null) { |
| | | sum = sum.add(o.getCloseMoney()); |
| | | } |
| | | } |
| | | // åâå
,2ä½å°æ° |
| | | return sum.divide(CENT_PER_YUAN, 2, BigDecimal.ROUND_HALF_UP); |
| | | } |
| | | |
| | | /** |
| | | * 计ç®å¢é¿ç:(current - base) / base à 100,ä¿ç2ä½å°æ°ã |
| | | * |
| | | * @param current æ¬æå¼ |
| | | * @param base å¯¹æ¯æå¼ |
| | | * @return å¢é¿ç(%);base 为 0 æ null æ¶è¿å null(æ æ³è®¡ç®,å端æ¾ç¤º"-") |
| | | */ |
| | | private BigDecimal growthRate(BigDecimal current, BigDecimal base) { |
| | | if (base == null || base.compareTo(BigDecimal.ZERO) == 0) { |
| | | // å¯¹æ¯ææ æ¶å
¥,å¢é¿çæ æä¹ |
| | | return null; |
| | | } |
| | | BigDecimal current0 = current == null ? BigDecimal.ZERO : current; |
| | | return current0.subtract(base) |
| | | .multiply(PERCENT_BASE) |
| | | .divide(base, 2, BigDecimal.ROUND_HALF_UP); |
| | | } |
| | | |
| | | @Override |
| | | public OperationCenterVO operationCenter() { |
| | | Date now = new Date(); |
| | | // 仿¥èµ·æ¢(å«ç«¯ç¹),ç¨äº"仿¥*"ç³»åç»è®¡ |
| | | Date todayStart = DateUtil.getStartOfDay(now); |
| | | Date todayEnd = DateUtil.getEndOfDay(now); |
| | | |
| | | OperationCenterVO vo = new OperationCenterVO(); |
| | | // 仿¥æ¥æ + ææå |
| | | vo.setToday(DateUtil.getShortDateStr(now)); |
| | | vo.setWeekDay(DateUtil.getWeekOfDate(now)); |
| | | |
| | | // 仿¥è®¢åæ»æ°:仿¥å·²æ¯ä»è®¢å(payStatus=1),å«éªè¡æ¼é(type=0)ä¸å¥é¤å¡(type=1) |
| | | vo.setTodayOrderCount((long) goodsorderMapper.selectCount( |
| | | new QueryWrapper<Goodsorder>().lambda() |
| | | .eq(Goodsorder::getPayStatus, Constants.ONE) |
| | | .eq(Goodsorder::getIsdeleted, Constants.ZERO) |
| | | .ge(Goodsorder::getPayDate, todayStart) |
| | | .le(Goodsorder::getPayDate, todayEnd))); |
| | | |
| | | // è¿è¡ä¸è®¢åæ°é:éªè¡ä¸(type=0 æ¼éãå·²æ¯ä»æªç»ç® status=1),宿¶å¨é,ä¸éæ¥æ |
| | | vo.setOngoingOrderCount((long) goodsorderMapper.selectCount( |
| | | new QueryWrapper<Goodsorder>().lambda() |
| | | .eq(Goodsorder::getType, Constants.ZERO) |
| | | .eq(Goodsorder::getStatus, Constants.ONE) |
| | | .eq(Goodsorder::getIsdeleted, Constants.ZERO))); |
| | | |
| | | // 仿¥å¥é¤æ¶å
¥(å
):仿¥å¥é¤å¡è´ä¹°(type=1ãå·²æ¯ä»)ç money ä¹å |
| | | vo.setPackageIncome(sumMoney(Constants.ONE, todayStart, todayEnd)); |
| | | |
| | | // 仿¥æ»æ¶å
¥(å
):䏿¶å
¥ç»è®¡åå£å¾(type=0 æ¼é + status=4 å·²ç»ç® ç closeMoney),å¤ç¨ |
| | | vo.setTotalIncome(sumClosedMoney(todayStart, todayEnd)); |
| | | |
| | | return vo; |
| | | } |
| | | |
| | | /** |
| | | * æ±æ»æå®è®¢åç±»å卿¶æ®µå
å·²æ¯ä»è®¢åçæ¯ä»éé¢(money ä¹å,åâå
)ã |
| | | * <p>ä¾è¿è¥ä¸å¿"仿¥å¥é¤æ¶å
¥"çæ type ç»è®¡æ¯ä»éé¢ä½¿ç¨ã |
| | | * |
| | | * @param type 订åç±»å(0 ç§è½¦æ¼é / 1 å¥é¤å¡è´ä¹°) |
| | | * @param start èµ·å§æ¶é´(å«) |
| | | * @param end ç»ææ¶é´(å«) |
| | | * @return åºé´æ¯ä»éé¢(å
,2ä½å°æ°);æ æ°æ®è¿å 0 |
| | | */ |
| | | private BigDecimal sumMoney(Integer type, Date start, Date end) { |
| | | List<Goodsorder> orders = goodsorderMapper.selectList( |
| | | new QueryWrapper<Goodsorder>().lambda() |
| | | .select(Goodsorder::getMoney) |
| | | .eq(Goodsorder::getType, type) |
| | | .eq(Goodsorder::getPayStatus, Constants.ONE) |
| | | .eq(Goodsorder::getIsdeleted, Constants.ZERO) |
| | | .ge(Goodsorder::getPayDate, start) |
| | | .le(Goodsorder::getPayDate, end)); |
| | | BigDecimal sum = BigDecimal.ZERO; |
| | | for (Goodsorder o : orders) { |
| | | if (o.getMoney() != null) { |
| | | sum = sum.add(o.getMoney()); |
| | | } |
| | | } |
| | | // åâå
,2ä½å°æ° |
| | | return sum.divide(CENT_PER_YUAN, 2, BigDecimal.ROUND_HALF_UP); |
| | | } |
| | | |
| | | @Override |
| | | public PageData<OperationOrderVO> operationOrderPage(PageWrap<OperationOrderQueryDTO> pageWrap) { |
| | | // å页对象 |
| | | IPage<OperationOrderVO> page = new Page<>(pageWrap.getPage(), pageWrap.getCapacity()); |
| | | OperationOrderQueryDTO model = pageWrap.getModel() == null |
| | | ? new OperationOrderQueryDTO() : pageWrap.getModel(); |
| | | |
| | | // ââ æ¥éª¤1:å页主æ¥è¯¢ ââ |
| | | // 主表 goodsorder left join member(åææºå·)+ left join base_param(åç»ç®è½¦åå); |
| | | // 订åç¶æ(status)æ å°å° VO å
鍿¿è½½å段,ä¾åå¡«åºå忰忝;ä¸å带éè¡åæ°åæ¥è¯¢ã |
| | | // 注:bikeType çéä»ç¨ inSql åæ¥è¯¢ââå®åªä½ WHERE æ¡ä»¶ãæ´é¡µæ§è¡ä¸æ¬¡,䏿¯éè¡æå½±,å¯ä¿çã |
| | | MPJLambdaWrapper<Goodsorder> wrapper = new MPJLambdaWrapper<Goodsorder>() |
| | | // ä¸»è¡¨åæ®µ:订å主é®ãç¼å·ãç»ç®æ¶é´ |
| | | .select(Goodsorder::getId, Goodsorder::getCode, Goodsorder::getCloseDate) |
| | | // 订åç¶æ:å
鍿¿è½½å段(@JsonIgnore,ä¸è¿åå端),ç¨äºå填忝夿 |
| | | .selectAs(Goodsorder::getStatus, OperationOrderVO::getOrderStatus) |
| | | // ç»ç®è½¦åå:å·²ç»ç®è®¢åç´æ¥ left join base_param å(goodsorder.param_idâbase_param.name) |
| | | .selectAs(BaseParam::getName, OperationOrderVO::getSettleParamName) |
| | | // ç¨æ·ææºå·:left join member |
| | | .selectAs(Member::getPhone, OperationOrderVO::getPhone) |
| | | .leftJoin(Member.class, Member::getId, Goodsorder::getMemberId) |
| | | .leftJoin(BaseParam.class, BaseParam::getId, Goodsorder::getParamId) |
| | | // åºå®æ¡ä»¶:é»è®¤åªæ¥æ¼é订å(type=0) |
| | | .eq(Goodsorder::getType, Constants.ZERO) |
| | | .eq(Goodsorder::getIsdeleted, Constants.ZERO) |
| | | // 订åç¶æ:1è¿è¡ä¸ / 4å·²å®ç»(å¯é) |
| | | .eq(Objects.nonNull(model.getStatus()), Goodsorder::getStatus, model.getStatus()) |
| | | // ç¨æ·ææºå·:模ç³å¹é
(å¯é) |
| | | .like(StringUtils.isNotBlank(model.getPhone()), Member::getPhone, model.getPhone()) |
| | | // 订åç±»å:æéªè¡è®°å½ member_rides.type çé(å¯é) |
| | | .inSql(Objects.nonNull(model.getBikeType()), Goodsorder::getId, |
| | | "select ordre_id from member_rides where isdeleted = 0 and type = " + model.getBikeType()) |
| | | .orderByDesc(Goodsorder::getPayDate); |
| | | IPage<OperationOrderVO> result = goodsorderMapper.selectJoinPage(page, OperationOrderVO.class, wrapper); |
| | | List<OperationOrderVO> records = result.getRecords(); |
| | | // æ æ°æ®ç´æ¥è¿å,é¿å
空 in() æ¥è¯¢ |
| | | if (records.isEmpty()) { |
| | | return PageData.from(result); |
| | | } |
| | | |
| | | // ââ æ¥éª¤2:æ¶éå½å页订å id ââ |
| | | List<String> orderIds = records.stream().map(OperationOrderVO::getId).collect(Collectors.toList()); |
| | | |
| | | // ââ æ¥éª¤3:䏿¬¡æ§æ¹éæ¥éªè¡è®°å½(å«éªè¡è½¦åå) ââ |
| | | // left join base_param ç´æ¥å¸¦åºéªè¡è½¦åå(member_rides.param_idâbase_param.nameâMemberRides.paramName); |
| | | // æ create_date desc æåº,å
åæè®¢ååç»åæ¯ç»ç¬¬ä¸æ¡å³"æè¿ä¸æ¡éªè¡è®°å½" |
| | | List<MemberRides> rides = memberRidesJoinMapper.selectJoinList(MemberRides.class, |
| | | new MPJLambdaWrapper<MemberRides>() |
| | | .select(MemberRides::getOrdreId, MemberRides::getType, MemberRides::getRentDate, |
| | | MemberRides::getBikeCode) |
| | | .selectAs(BaseParam::getName, MemberRides::getParamName) |
| | | .leftJoin(BaseParam.class, BaseParam::getId, MemberRides::getParamId) |
| | | .eq(MemberRides::getIsdeleted, Constants.ZERO) |
| | | .in(MemberRides::getOrdreId, orderIds) |
| | | .orderByDesc(MemberRides::getCreateDate) |
| | | .orderByDesc(MemberRides::getRentDate)); |
| | | Map<String, MemberRides> latestRideByOrder = new LinkedHashMap<>(); |
| | | for (MemberRides r : rides) { |
| | | // putIfAbsent:å·²æ create_date desc æåº,馿¬¡åºç°å³è¯¥è®¢åæè¿ä¸æ¡ |
| | | latestRideByOrder.putIfAbsent(r.getOrdreId(), r); |
| | | } |
| | | |
| | | // ââ åå¡« VO(å
¨ç¨ä»
2 次æ¥è¯¢:å页 / éªè¡;车åååç± join 带åº,æ éåç¬æ¥è½¦ååå
¸) ââ |
| | | for (OperationOrderVO vo : records) { |
| | | MemberRides latest = latestRideByOrder.get(vo.getId()); |
| | | // 车åå忝:è¿è¡ä¸(status=1)åæè¿éªè¡ç车åå,å¦å(å«å·²ç»ç®)å订åç»ç®è½¦åå |
| | | Integer orderStatus = vo.getOrderStatus(); |
| | | boolean inProgress = orderStatus != null && orderStatus.equals(Constants.ONE); |
| | | if (latest != null) { |
| | | // 订åç±»åãéªè¡å¼å§æ¶é´ã车è¾ç¼å·:ç»ä¸åæè¿ä¸æ¡éªè¡è®°å½ |
| | | // (è¿è¡ä¸å³"å½åéªè¡è½¦è¾",å·²å®ç»å³"æåéªè¡è½¦è¾";bike_code = bikes.code) |
| | | vo.setBikeType(latest.getType()); |
| | | vo.setRentDate(latest.getRentDate()); |
| | | if (inProgress) { |
| | | // è¿è¡ä¸:éªè¡è½¦åå(join 已带åº,åäº MemberRides.paramName) |
| | | vo.setParamName(latest.getParamName()); |
| | | vo.setBikeCode(latest.getBikeCode()); |
| | | } |
| | | } |
| | | if (!inProgress) { |
| | | // å·²ç»ç®:订åç»ç®è½¦åå(å页 join 已带åº,åäº settleParamName) |
| | | vo.setParamName(vo.getSettleParamName()); |
| | | } |
| | | } |
| | | |
| | | return PageData.from(result); |
| | | } |
| | | |
| | | @Override |
| | | public OrderRidesDetailVO orderRidesDetail(String orderId) { |
| | | OrderRidesDetailVO result = new OrderRidesDetailVO(); |
| | | // 订åå·ä¸ºç©º:ç´æ¥è¿åç©ºç»æ(䏿å¼å¸¸,å端æ hasTrack=false å
åº) |
| | | if (StringUtils.isBlank(orderId)) { |
| | | result.setHasTrack(false); |
| | | result.setRides(Collections.emptyList()); |
| | | return result; |
| | | } |
| | | |
| | | // 1. æ¥è¯¥è®¢åä¸å
¨é¨éªè¡è®°å½(æå建æ¶é´ååº,è¿ååä¸è®¢å夿¬¡éªè¡çå
å) |
| | | List<MemberRides> ridesList = memberRidesJoinMapper.selectList( |
| | | new QueryWrapper<MemberRides>().lambda() |
| | | .eq(MemberRides::getOrdreId, orderId) |
| | | .eq(MemberRides::getIsdeleted, Constants.ZERO) |
| | | .orderByAsc(MemberRides::getCreateDate)); |
| | | if (ridesList.isEmpty()) { |
| | | // 订å䏿 éªè¡è®°å½(ç论ä¸åºåºç°,å
åºè¿å空) |
| | | result.setHasTrack(false); |
| | | result.setRides(Collections.emptyList()); |
| | | return result; |
| | | } |
| | | |
| | | // 2. 车è¾ç±»åå馿¡éªè¡ type(0èªè¡è½¦/1çµè½¦):å³å®æ¯å¦æ¥è½¨è¿¹ |
| | | Integer bikeType = ridesList.get(0).getType(); |
| | | result.setBikeType(bikeType); |
| | | result.setBikeTypeName(bikeTypeNameOf(bikeType)); |
| | | boolean isEbike = bikeType != null && bikeType.equals(Constants.ONE); |
| | | |
| | | // 3. 轨迹é¢è½½(ä»
çµè½¦):䏿¬¡æ§æ¥åºè¯¥è®¢åææéªè¡è½¨è¿¹,æ rides_id åç»ãæä¸æ¥æ¶é´ååº, |
| | | // é¿å
éæ¡éªè¡ N 次æ¥è½¨è¿¹;èªè¡è½¦(type=0)èµ° MQTT æ GPS,è·³è¿ã |
| | | Map<String, List<OrderRideTrackVO>> trackByRide = new HashMap<>(); |
| | | if (isEbike) { |
| | | List<String> ridesIds = ridesList.stream() |
| | | .map(MemberRides::getId).collect(Collectors.toList()); |
| | | List<MemberRidesTrack> tracks = memberRidesTrackMapper.selectList( |
| | | new QueryWrapper<MemberRidesTrack>().lambda() |
| | | .select(MemberRidesTrack::getRidesId, MemberRidesTrack::getLongitude, |
| | | MemberRidesTrack::getLatitude, MemberRidesTrack::getReportTime) |
| | | .eq(MemberRidesTrack::getIsdeleted, Constants.ZERO) |
| | | .in(MemberRidesTrack::getRidesId, ridesIds) |
| | | .orderByAsc(MemberRidesTrack::getReportTime)); |
| | | for (MemberRidesTrack t : tracks) { |
| | | OrderRideTrackVO tv = new OrderRideTrackVO(); |
| | | tv.setLongitude(t.getLongitude()); |
| | | tv.setLatitude(t.getLatitude()); |
| | | tv.setReportTime(t.getReportTime()); |
| | | trackByRide.computeIfAbsent(t.getRidesId(), k -> new ArrayList<>()).add(tv); |
| | | } |
| | | } |
| | | |
| | | // 4. ç»è£
éªè¡è®°å½å表(æ¯æ¡æå¯¹åºè½¨è¿¹ç¹;èªè¡è½¦ä¸å¾ç©ºè½¨è¿¹) |
| | | List<OrderRideItemVO> rides = new ArrayList<>(ridesList.size()); |
| | | for (MemberRides r : ridesList) { |
| | | OrderRideItemVO item = new OrderRideItemVO(); |
| | | item.setRidesId(r.getId()); |
| | | item.setStatus(r.getStatus()); |
| | | item.setStatusName(rideStatusNameOf(r.getStatus())); |
| | | item.setRentDate(r.getRentDate()); |
| | | item.setBackDate(r.getBackDate()); |
| | | item.setBikeCode(r.getBikeCode()); |
| | | item.setDuration(r.getDuration()); |
| | | item.setBikeTypeName(bikeTypeNameOf(r.getType())); |
| | | item.setTracks(isEbike |
| | | ? trackByRide.getOrDefault(r.getId(), Collections.emptyList()) |
| | | : Collections.emptyList()); |
| | | rides.add(item); |
| | | } |
| | | result.setRides(rides); |
| | | |
| | | // 5. 轨迹å¯ç¨æ§ + èªè¡è½¦æ 轨迹æç¤º |
| | | if (isEbike) { |
| | | result.setHasTrack(true); |
| | | } else { |
| | | result.setHasTrack(false); |
| | | result.setNoTrackMessage("该订å为èªè¡è½¦è®¢å,æ 车è¾è½¨è¿¹"); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * éªè¡ç¶æ â 䏿åã |
| | | * <p>member_rides.status:0请æ±å¼éä¸ / 1éªè¡ä¸ / 2å·²è¿è½¦ / 3å¼é失败 / 4临æ¶é车ã |
| | | * |
| | | * @param status éªè¡ç¶æåæ(å¯è½ä¸º null) |
| | | * @return ç¶æä¸æå(空å¼/æªç¥åå¼è¿å"æªç¥") |
| | | */ |
| | | private String rideStatusNameOf(Integer status) { |
| | | if (status == null) { |
| | | return "æªç¥"; |
| | | } |
| | | switch (status) { |
| | | case 0: |
| | | return "请æ±å¼éä¸"; |
| | | case 1: |
| | | return "éªè¡ä¸"; |
| | | case 2: |
| | | return "å·²è¿è½¦"; |
| | | case 3: |
| | | return "å¼é失败"; |
| | | case 4: |
| | | return "临æ¶é车"; |
| | | default: |
| | | return "æªç¥"; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 车è¾ç±»å â 䏿åã |
| | | * <p>member_rides.type:0èªè¡è½¦ / 1çµå¨è½¦ã |
| | | * |
| | | * @param type 车è¾ç±»å(å¯è½ä¸º null) |
| | | * @return ç±»å䏿å(æªç¥åå¼è¿å"æªç¥") |
| | | */ |
| | | private String bikeTypeNameOf(Integer type) { |
| | | if (type == null) { |
| | | return "æªç¥"; |
| | | } |
| | | if (type.equals(Constants.ZERO)) { |
| | | return "èªè¡è½¦"; |
| | | } |
| | | if (type.equals(Constants.ONE)) { |
| | | return "çµå¨è½¦"; |
| | | } |
| | | return "æªç¥"; |
| | | } |
| | | |
| | | @Override |
| | | public IncomeStatVO incomeStat30() { |
| | | // è¿30天(å«ä»å¤©å
±30天),å¤ç¨ incomeStat æ¢æå®ç°ä¸å£å¾ |
| | | BikeIncomeQueryDTO query = new BikeIncomeQueryDTO(); |
| | | query.setDateType(3); |
| | | return incomeStat(query); |
| | | } |
| | | |
| | | @Override |
| | | public BikeUsageStatVO bikeUsageStat() { |
| | | // status:0 ç©ºé² / 1 使ç¨ä¸;ç¦ç¨(3)ä¸è®¡å
¥;type:0 èªè¡è½¦ / 1 çµå¨è½¦ |
| | | BikeUsageStatVO vo = new BikeUsageStatVO(); |
| | | vo.setBikeIdle(countBikeByStatus(Constants.ZERO, Constants.ZERO)); |
| | | vo.setBikeInUse(countBikeByStatus(Constants.ZERO, Constants.ONE)); |
| | | vo.setEleBikeIdle(countBikeByStatus(Constants.ONE, Constants.ZERO)); |
| | | vo.setEleBikeInUse(countBikeByStatus(Constants.ONE, Constants.ONE)); |
| | | return vo; |
| | | } |
| | | |
| | | /** |
| | | * æè½¦è¾ç±»å + ç¶æç»è®¡æªå é¤è½¦è¾æ°éã |
| | | * |
| | | * @param type 车è¾ç±»å 0 èªè¡è½¦ / 1 çµå¨è½¦ |
| | | * @param status 车è¾ç¶æ 0 ç©ºé² / 1 使ç¨ä¸ |
| | | * @return 满足æ¡ä»¶çè½¦è¾æ° |
| | | */ |
| | | private long countBikeByStatus(Integer type, Integer status) { |
| | | return bikesMapper.selectCount( |
| | | new QueryWrapper<Bikes>().lambda() |
| | | .eq(Bikes::getType, type) |
| | | .eq(Bikes::getStatus, status) |
| | | .eq(Bikes::getIsdeleted, Constants.ZERO)); |
| | | } |
| | | |
| | | @Override |
| | | public PackageSourceStatVO packageSourceStat() { |
| | | // æ¬æ/æ¬å¹´èµ·æ¢(pay_date è½å¨åºé´å
);goodsorder type=1 å¥é¤å¡è´ä¹° + payStatus=1 å·²æ¯ä» |
| | | Calendar cal = Calendar.getInstance(); |
| | | Date monthStart = DateUtil.getStartOfDay(getFirstMs(cal, Calendar.MONTH)); |
| | | Date monthEnd = DateUtil.getEndOfDay(new Date()); |
| | | Date yearStart = DateUtil.getStartOfDay(getFirstMs(cal, Calendar.YEAR)); |
| | | Date yearEnd = DateUtil.getEndOfDay(new Date()); |
| | | |
| | | PackageSourceStatVO vo = new PackageSourceStatVO(); |
| | | vo.setMonth(countPackageSource(monthStart, monthEnd)); |
| | | vo.setYear(countPackageSource(yearStart, yearEnd)); |
| | | return vo; |
| | | } |
| | | |
| | | /** |
| | | * ç»è®¡æå®æ¶æ®µå
å¥é¤é宿¥æºæ°éã |
| | | * <p>æé³å
æ¢ = payWay 2,å°ç¨åºè´ä¹° = payWay 0(微信)ã |
| | | * |
| | | * @param start èµ·å§æ¶é´(å«) |
| | | * @param end ç»ææ¶é´(å«) |
| | | * @return æé³/å°ç¨åºå¥é¤æ°é |
| | | */ |
| | | private PackageSourceStatVO.PeriodCount countPackageSource(Date start, Date end) { |
| | | List<Goodsorder> orders = goodsorderMapper.selectList( |
| | | new QueryWrapper<Goodsorder>().lambda() |
| | | .select(Goodsorder::getPayWay) |
| | | .eq(Goodsorder::getType, Constants.ONE) |
| | | .eq(Goodsorder::getPayStatus, Constants.ONE) |
| | | .eq(Goodsorder::getIsdeleted, Constants.ZERO) |
| | | .ge(Goodsorder::getPayDate, start) |
| | | .le(Goodsorder::getPayDate, end)); |
| | | long douyin = 0L; |
| | | long mini = 0L; |
| | | for (Goodsorder o : orders) { |
| | | if (o.getPayWay() == null) { |
| | | continue; |
| | | } |
| | | if (o.getPayWay() == PAY_WAY_DOUYIN) { |
| | | douyin++; |
| | | } else if (o.getPayWay() == Constants.ZERO) { |
| | | mini++; |
| | | } |
| | | } |
| | | PackageSourceStatVO.PeriodCount pc = new PackageSourceStatVO.PeriodCount(); |
| | | pc.setDouyinCount(douyin); |
| | | pc.setMiniCount(mini); |
| | | return pc; |
| | | } |
| | | |
| | | @Override |
| | | public DashboardVO dashboard() { |
| | | DashboardVO vo = new DashboardVO(); |
| | | |
| | | // åæ¶æ®µèµ·æ¢:æ¬æ/æ¨æ¥/仿¥ |
| | | Date now = new Date(); |
| | | Calendar cal = Calendar.getInstance(); |
| | | Date monthStart = DateUtil.getStartOfDay(getFirstMs(cal, Calendar.MONTH)); |
| | | Date monthEnd = DateUtil.getEndOfDay(now); |
| | | Date yesterdayStart = DateUtil.getStartOfDay(DateUtil.increaseDay(now, -1)); |
| | | Date yesterdayEnd = DateUtil.getEndOfDay(DateUtil.increaseDay(now, -1)); |
| | | Date todayStart = DateUtil.getStartOfDay(now); |
| | | Date todayEnd = DateUtil.getEndOfDay(now); |
| | | |
| | | // æ¶ç(å£å¾å incomeStat:type=0 æ¼é + status=4 å·²ç»ç® ç closeMoney),å¤ç¨ sumClosedMoney |
| | | vo.setMonthIncome(sumClosedMoney(monthStart, monthEnd)); |
| | | vo.setYesterdayIncome(sumClosedMoney(yesterdayStart, yesterdayEnd)); |
| | | vo.setTodayIncome(sumClosedMoney(todayStart, todayEnd)); |
| | | |
| | | // è®¢åæ°:å·²æ¯ä»(payStatus=1)订åè®¡æ° |
| | | vo.setMonthOrderCount(countPaidOrders(monthStart, monthEnd)); |
| | | vo.setYesterdayOrderCount(countPaidOrders(yesterdayStart, yesterdayEnd)); |
| | | vo.setTodayOrderCount(countPaidOrders(todayStart, todayEnd)); |
| | | |
| | | // 车è¾:ä»
è¿åæªå 餿»æ° |
| | | vo.setTotalBikeCount((long) bikesMapper.selectCount( |
| | | new QueryWrapper<Bikes>().lambda().eq(Bikes::getIsdeleted, Constants.ZERO))); |
| | | |
| | | // å®¢æ·æ°:æ»ä¼å=æªå é¤å
¨é¨;仿¥/æ¨æ¥æ°å¢æ create_date è½å¨å¯¹åºåºé´(ä¸ overview å£å¾ä¸è´) |
| | | vo.setTotalMemberCount((long) memberMapper.selectCount( |
| | | new QueryWrapper<Member>().lambda().eq(Member::getIsdeleted, Constants.ZERO))); |
| | | vo.setYesterdayNewMember((long) memberMapper.selectCount( |
| | | new QueryWrapper<Member>().lambda() |
| | | .eq(Member::getIsdeleted, Constants.ZERO) |
| | | .ge(Member::getCreateDate, yesterdayStart) |
| | | .le(Member::getCreateDate, yesterdayEnd))); |
| | | vo.setTodayNewMember((long) memberMapper.selectCount( |
| | | new QueryWrapper<Member>().lambda() |
| | | .eq(Member::getIsdeleted, Constants.ZERO) |
| | | .ge(Member::getCreateDate, todayStart))); |
| | | return vo; |
| | | } |
| | | |
| | | /** |
| | | * ç»è®¡æå®æ¶æ®µå
å·²æ¯ä»è®¢åæ°é(payStatus=1)ã |
| | | * |
| | | * @param start èµ·å§æ¶é´(å«) |
| | | * @param end ç»ææ¶é´(å«) |
| | | * @return å·²æ¯ä»è®¢åæ° |
| | | */ |
| | | private long countPaidOrders(Date start, Date end) { |
| | | return goodsorderMapper.selectCount( |
| | | new QueryWrapper<Goodsorder>().lambda() |
| | | .eq(Goodsorder::getPayStatus, Constants.ONE) |
| | | .eq(Goodsorder::getIsdeleted, Constants.ZERO) |
| | | .ge(Goodsorder::getPayDate, start) |
| | | .le(Goodsorder::getPayDate, end)); |
| | | } |
| | | |
| | | /** |
| | | * 忬æ/æ¬å¹´ç¬¬ä¸å¤©çæ¶é´åå¼(æ¶åç§å½é¶åçæ¯«ç§),ç¨äºæé åºé´èµ·å§ã |
| | | * <p>ç¨ Calendar æã彿1æ¥ 00:00:00.000ãæãå½å¹´1æ1æ¥ 00:00:00.000ãååºã |
| | | * |
| | | * @param cal æ¥å(ä¼è¢«ä¿®æ¹) |
| | | * @param field Calendar.MONTH æ¬æç¬¬ä¸å¤© / Calendar.YEAR æ¬å¹´ç¬¬ä¸å¤© |
| | | * @return åºé´èµ·å§æ¶é´ |
| | | */ |
| | | private Date getFirstMs(Calendar cal, int field) { |
| | | cal.setTime(new Date()); |
| | | if (field == Calendar.MONTH) { |
| | | cal.set(Calendar.DAY_OF_MONTH, 1); |
| | | } else { |
| | | cal.set(Calendar.MONTH, Calendar.JANUARY); |
| | | cal.set(Calendar.DAY_OF_MONTH, 1); |
| | | } |
| | | cal.set(Calendar.HOUR_OF_DAY, 0); |
| | | cal.set(Calendar.MINUTE, 0); |
| | | cal.set(Calendar.SECOND, 0); |
| | | cal.set(Calendar.MILLISECOND, 0); |
| | | return cal.getTime(); |
| | | } |
| | | } |