瀏覽代碼

物业费管理

LIVE_YE 2 月之前
父節點
當前提交
2cfa3d4300

+ 16 - 0
ruoyi-modules/ruoyi-wuye/src/main/java/org/dromara/controller/houseInfo/HouseInfoController.java

@@ -8,6 +8,7 @@ import lombok.RequiredArgsConstructor;
 import org.dromara.common.core.domain.R;
 import org.dromara.common.core.validate.AddGroup;
 import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.excel.core.ExcelResult;
 import org.dromara.common.excel.utils.ExcelUtil;
 import org.dromara.common.idempotent.annotation.RepeatSubmit;
 import org.dromara.common.log.annotation.Log;
@@ -17,9 +18,11 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.web.core.BaseController;
 import org.dromara.domain.houseInfo.bo.HouseInfoBo;
 import org.dromara.domain.houseInfo.vo.HouseInfoVo;
+import org.dromara.listener.HouseInfoImportListener;
 import org.dromara.service.IHouseInfoService;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 
 import java.util.List;
 
@@ -57,6 +60,19 @@ public class HouseInfoController extends BaseController {
         ExcelUtil.exportExcel(list, "房屋信息", HouseInfoVo.class, response);
     }
 
+    /**
+     * 导入房屋信息列表
+     * @param file
+     * @return
+     * @throws Exception
+     */
+    @PostMapping("/importData")
+    public R<Void> importData(@RequestPart("file") MultipartFile file, boolean updateSupport) throws Exception
+    {
+        ExcelResult<HouseInfoVo> result = ExcelUtil.importExcel(file.getInputStream(), HouseInfoVo.class, new HouseInfoImportListener());
+        return R.ok(result.getAnalysis());
+    }
+
     /**
      * 获取房屋信息详细信息
      *

+ 35 - 0
ruoyi-modules/ruoyi-wuye/src/main/java/org/dromara/controller/houseInfo/PropertyFeeController.java

@@ -21,7 +21,9 @@ import org.dromara.service.IPropertyFeeService;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
+import java.math.BigDecimal;
 import java.util.List;
+import java.util.Map;
 
 /**
  * 物业费管理
@@ -103,4 +105,37 @@ public class PropertyFeeController extends BaseController {
                           @PathVariable Long[] propertyIds) {
         return toAjax(propertyFeeService.deleteWithValidByIds(List.of(propertyIds), true));
     }
+
+    /**
+     * 物业费统计
+     */
+    @SaCheckPermission("wuYe:fee:statistics")
+    @Log(title = "物业费管理", businessType = BusinessType.DELETE)
+    @GetMapping("/statistics")
+    public R<Map<String, BigDecimal>> statistics(@RequestBody PropertyFeeBo bo)
+    {
+        return propertyFeeService.statistics(bo);
+    }
+
+    /**
+     * 物业费催缴
+     */
+    @SaCheckPermission("wuYe:fee:callPayment")
+    @Log(title = "物业费管理", businessType = BusinessType.DELETE)
+    @GetMapping("/callPayment/{houseId}")
+    public R<Void> CallPayment(@PathVariable Long houseId)
+    {
+        return propertyFeeService.CallPayment(houseId);
+    }
+
+    /**
+     * 物业费催缴(一键催缴)
+     */
+    @SaCheckPermission("wuYe:fee:callPaymentAll")
+    @Log(title = "物业费管理", businessType = BusinessType.DELETE)
+    @GetMapping("/callPaymentAll")
+    public R<Void> CallPaymentAll(@RequestBody PropertyFeeBo bo)
+    {
+        return propertyFeeService.CallPaymentAll(bo);
+    }
 }

+ 5 - 4
ruoyi-modules/ruoyi-wuye/src/main/java/org/dromara/domain/houseInfo/PropertyFee.java

@@ -6,6 +6,7 @@ import lombok.Data;
 import lombok.EqualsAndHashCode;
 
 import java.io.Serial;
+import java.math.BigDecimal;
 
 /**
  * 物业费管理对象 property_fee
@@ -85,22 +86,22 @@ public class PropertyFee extends TenantEntity {
     /**
      * 应缴物业费用
      */
-    private Long tenementExpense;
+    private BigDecimal tenementExpense;
 
     /**
      * 应缴车位费用
      */
-    private Long parkingExpense;
+    private BigDecimal parkingExpense;
 
     /**
      * 应缴能耗费用
      */
-    private Long energyExpense;
+    private BigDecimal energyExpense;
 
     /**
      * 应缴总费用
      */
-    private Long totalExpense;
+    private BigDecimal totalExpense;
 
     /**
      * 是否缴费,Y表示有,N表示无

+ 6 - 4
ruoyi-modules/ruoyi-wuye/src/main/java/org/dromara/domain/houseInfo/bo/PropertyFeeBo.java

@@ -9,6 +9,8 @@ import org.dromara.common.core.validate.EditGroup;
 import org.dromara.common.mybatis.core.domain.BaseEntity;
 import org.dromara.domain.houseInfo.PropertyFee;
 
+import java.math.BigDecimal;
+
 /**
  * 物业费管理业务对象 property_fee
  *
@@ -84,22 +86,22 @@ public class PropertyFeeBo extends BaseEntity {
     /**
      * 应缴物业费用
      */
-    private Long tenementExpense;
+    private BigDecimal tenementExpense;
 
     /**
      * 应缴车位费用
      */
-    private Long parkingExpense;
+    private BigDecimal parkingExpense;
 
     /**
      * 应缴能耗费用
      */
-    private Long energyExpense;
+    private BigDecimal energyExpense;
 
     /**
      * 应缴总费用
      */
-    private Long totalExpense;
+    private BigDecimal totalExpense;
 
     /**
      * 是否缴费,Y表示有,N表示无

+ 5 - 5
ruoyi-modules/ruoyi-wuye/src/main/java/org/dromara/domain/houseInfo/vo/PropertyFeeVo.java

@@ -8,7 +8,7 @@ import org.dromara.domain.houseInfo.PropertyFee;
 
 import java.io.Serial;
 import java.io.Serializable;
-
+import java.math.BigDecimal;
 
 
 /**
@@ -101,25 +101,25 @@ public class PropertyFeeVo implements Serializable {
      * 应缴物业费用
      */
     @ExcelProperty(value = "应缴物业费用")
-    private Long tenementExpense;
+    private BigDecimal tenementExpense;
 
     /**
      * 应缴车位费用
      */
     @ExcelProperty(value = "应缴车位费用")
-    private Long parkingExpense;
+    private BigDecimal parkingExpense;
 
     /**
      * 应缴能耗费用
      */
     @ExcelProperty(value = "应缴能耗费用")
-    private Long energyExpense;
+    private BigDecimal energyExpense;
 
     /**
      * 应缴总费用
      */
     @ExcelProperty(value = "应缴总费用")
-    private Long totalExpense;
+    private BigDecimal totalExpense;
 
     /**
      * 是否缴费,Y表示有,N表示无

+ 99 - 0
ruoyi-modules/ruoyi-wuye/src/main/java/org/dromara/listener/HouseInfoImportListener.java

@@ -0,0 +1,99 @@
+package org.dromara.listener;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.http.HtmlUtil;
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.event.AnalysisEventListener;
+import jakarta.validation.ConstraintViolation;
+import jakarta.validation.ConstraintViolationException;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.common.core.exception.ServiceException;
+import org.dromara.common.core.utils.SpringUtils;
+import org.dromara.common.core.utils.StreamUtils;
+import org.dromara.common.core.utils.ValidatorUtils;
+import org.dromara.common.excel.core.ExcelListener;
+import org.dromara.common.excel.core.ExcelResult;
+import org.dromara.common.satoken.utils.LoginHelper;
+import org.dromara.domain.houseInfo.bo.HouseInfoBo;
+import org.dromara.domain.houseInfo.vo.HouseInfoVo;
+import org.dromara.service.IHouseInfoService;
+
+import java.util.List;
+
+/**
+ * 系统用户自定义导入
+ *
+ * @author Lion Li
+ */
+@Slf4j
+public class HouseInfoImportListener extends AnalysisEventListener<HouseInfoVo> implements ExcelListener<HouseInfoVo> {
+
+    private final IHouseInfoService houseInfoService;
+
+    private final Long operUserId;
+
+    private int successNum = 0;
+    private int failureNum = 0;
+    private final StringBuilder successMsg = new StringBuilder();
+    private final StringBuilder failureMsg = new StringBuilder();
+
+
+    public HouseInfoImportListener() {
+        this.houseInfoService = SpringUtils.getBean(IHouseInfoService.class);
+        this.operUserId = LoginHelper.getUserId();
+    }
+
+    @Override
+    public void invoke(HouseInfoVo houseVo, AnalysisContext context) {
+        try {
+            HouseInfoBo houseInfo = BeanUtil.toBean(houseVo, HouseInfoBo.class);
+            ValidatorUtils.validate(houseInfo);
+            houseInfo.setCreateBy(operUserId);
+            houseInfoService.insertByBo(houseInfo);
+            successNum++;
+            successMsg.append("<br/>").append(successNum).append("、账号 ").append(houseInfo.getPropertyUnitNumber()).append(" 导入成功");
+
+        } catch (Exception e) {
+            failureNum++;
+            String msg = "<br/>" + failureNum + "、账号 " + HtmlUtil.cleanHtmlTag(houseVo.getPropertyUnitNumber()) + " 导入失败:";
+            String message = e.getMessage();
+            if (e instanceof ConstraintViolationException cvException) {
+                message = StreamUtils.join(cvException.getConstraintViolations(), ConstraintViolation::getMessage, ", ");
+            }
+            failureMsg.append(msg).append(message);
+            log.error(msg, e);
+        }
+    }
+
+    @Override
+    public void doAfterAllAnalysed(AnalysisContext context) {
+
+    }
+
+    @Override
+    public ExcelResult<HouseInfoVo> getExcelResult() {
+        return new ExcelResult<>() {
+
+            @Override
+            public String getAnalysis() {
+                if (failureNum > 0) {
+                    failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
+                    throw new ServiceException(failureMsg.toString());
+                } else {
+                    successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
+                }
+                return successMsg.toString();
+            }
+
+            @Override
+            public List<HouseInfoVo> getList() {
+                return null;
+            }
+
+            @Override
+            public List<String> getErrorList() {
+                return null;
+            }
+        };
+    }
+}

+ 10 - 0
ruoyi-modules/ruoyi-wuye/src/main/java/org/dromara/service/IPropertyFeeService.java

@@ -1,13 +1,16 @@
 package org.dromara.service;
 
 
+import org.dromara.common.core.domain.R;
 import org.dromara.common.mybatis.core.page.PageQuery;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.domain.houseInfo.bo.PropertyFeeBo;
 import org.dromara.domain.houseInfo.vo.PropertyFeeVo;
 
+import java.math.BigDecimal;
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 
 /**
  * 物业费管理Service接口
@@ -66,4 +69,11 @@ public interface IPropertyFeeService {
      * @return 是否删除成功
      */
     Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+
+
+    R<Map<String, BigDecimal>> statistics(PropertyFeeBo bo);
+
+    R<Void> CallPayment(Long houseId);
+
+    R<Void> CallPaymentAll(PropertyFeeBo bo);
 }

+ 80 - 0
ruoyi-modules/ruoyi-wuye/src/main/java/org/dromara/service/impl/PropertyFeeServiceImpl.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import lombok.RequiredArgsConstructor;
+import org.dromara.common.core.domain.R;
 import org.dromara.common.core.utils.MapstructUtils;
 import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.mybatis.core.page.PageQuery;
@@ -11,11 +12,18 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.domain.houseInfo.PropertyFee;
 import org.dromara.domain.houseInfo.bo.PropertyFeeBo;
 import org.dromara.domain.houseInfo.vo.PropertyFeeVo;
+import org.dromara.domain.residentInfo.bo.ResidentInfoBo;
+import org.dromara.domain.residentInfo.vo.ResidentInfoVo;
 import org.dromara.mapper.PropertyFeeMapper;
 import org.dromara.service.IPropertyFeeService;
+import org.dromara.service.IResidentInfoService;
+import org.dromara.utils.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.math.BigDecimal;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -31,6 +39,9 @@ public class PropertyFeeServiceImpl implements IPropertyFeeService {
 
     private final PropertyFeeMapper baseMapper;
 
+    @Autowired
+    private IResidentInfoService residentInfoService;
+
     /**
      * 查询物业费管理
      *
@@ -142,4 +153,73 @@ public class PropertyFeeServiceImpl implements IPropertyFeeService {
         }
         return baseMapper.deleteByIds(ids) > 0;
     }
+
+    @Override
+    public R<Map<String, BigDecimal>> statistics(PropertyFeeBo bo) {
+        Map<String,BigDecimal> map = new HashMap<>();
+        //物业费
+        BigDecimal yjwyf = new BigDecimal("0.00");
+        BigDecimal wjwyf = new BigDecimal("0.00");
+
+        //车位费
+        BigDecimal yjcwf = new BigDecimal("0.00");
+        BigDecimal wjcwf = new BigDecimal("0.00");
+
+        //能耗费
+        BigDecimal yjnhf = new BigDecimal("0.00");
+        BigDecimal wjnhf = new BigDecimal("0.00");
+
+        //查询本年份所有数据并统计
+        if(StringUtils.isEmpty(bo.getYear())){
+            bo.setYear(DateUtils.getYear());
+        }
+
+        List<PropertyFeeVo> propertyFees = queryList(bo);
+        if(propertyFees!=null && propertyFees.size()>0){
+            for (PropertyFeeVo fee : propertyFees) {
+                if("Y".equals(fee.getIsExpense())){
+                    yjwyf = yjwyf.add(fee.getTenementExpense());
+                    yjcwf = yjcwf.add(fee.getParkingExpense());
+                    yjnhf = yjnhf.add(fee.getEnergyExpense());
+                }else{
+                    wjwyf = wjwyf.add(fee.getTenementExpense());
+                    wjcwf = wjcwf.add(fee.getParkingExpense());
+                    wjnhf = wjnhf.add(fee.getEnergyExpense());
+                }
+            }
+        }
+        map.put("yjwyf",yjwyf);
+        map.put("wjwyf",wjwyf);
+        map.put("yjcwf",yjcwf);
+        map.put("wjcwf",wjcwf);
+        map.put("yjnhf",yjnhf);
+        map.put("wjnhf",wjnhf);
+        return R.ok(map);
+    }
+
+    @Override
+    public R<Void> CallPayment(Long houseId) {
+        //查询户主信息
+        ResidentInfoBo bo = new ResidentInfoBo();
+        bo.setHouseId(houseId);
+        bo.setIsHouseholder("Y");
+        List<ResidentInfoVo> residentInfos = residentInfoService.queryList(bo);
+        if(residentInfos!=null && residentInfos.size()>0){
+            //todo 拿到户主手机号发送短信
+
+            return R.ok("催缴成功,已通知户主缴费");
+        }
+        return R.fail("催缴失败,当前房屋无户主信息");
+    }
+
+    @Override
+    public R<Void> CallPaymentAll(PropertyFeeBo bo) {
+        //查询所有未缴费信息
+        bo.setIsExpense("N");
+        List<PropertyFeeVo> propertyFees = queryList(bo);
+        //todo 通过房屋id拿到户主手机号发送短信
+
+
+        return R.ok("催缴成功,已通知户主缴费");
+    }
 }

+ 225 - 0
ruoyi-modules/ruoyi-wuye/src/main/java/org/dromara/utils/DateUtils.java

@@ -0,0 +1,225 @@
+package org.dromara.utils;
+
+import org.apache.commons.lang3.time.DateFormatUtils;
+
+import java.lang.management.ManagementFactory;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.*;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 时间工具类
+ *
+ * @author ruoyi
+ */
+public class DateUtils extends org.apache.commons.lang3.time.DateUtils
+{
+    public static String YYYY = "yyyy";
+
+    public static String YYYY_MM = "yyyy-MM";
+
+    public static String YYYY_MM_DD = "yyyy-MM-dd";
+
+    public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
+
+    public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
+
+    private static String[] parsePatterns = {
+            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
+            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
+            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
+
+    /**
+     * 获取当前Date型日期
+     *
+     * @return Date() 当前日期
+     */
+    public static Date getNowDate()
+    {
+        return new Date();
+    }
+
+    /**
+     * 获取当前日期, 默认格式为yyyy-MM-dd
+     *
+     * @return String
+     */
+    public static String getDate()
+    {
+        return dateTimeNow(YYYY_MM_DD);
+    }
+
+    public static String getYear()
+    {
+        return dateTimeNow(YYYY);
+    }
+    public static String getMonth()
+    {
+        return dateTimeNow(YYYY_MM);
+    }
+
+    public static final String getTime()
+    {
+        return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
+    }
+
+    public static final String dateTimeNow()
+    {
+        return dateTimeNow(YYYYMMDDHHMMSS);
+    }
+
+    public static final String dateTimeNow(final String format)
+    {
+        return parseDateToStr(format, new Date());
+    }
+
+    public static final String dateTime(final Date date)
+    {
+        return parseDateToStr(YYYY_MM_DD, date);
+    }
+
+    public static final String parseDateToStr(final String format, final Date date)
+    {
+        return new SimpleDateFormat(format).format(date);
+    }
+
+    public static final Date dateTime(final String format, final String ts)
+    {
+        try
+        {
+            return new SimpleDateFormat(format).parse(ts);
+        }
+        catch (ParseException e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * 日期路径 即年/月/日 如2018/08/08
+     */
+    public static final String datePath()
+    {
+        Date now = new Date();
+        return DateFormatUtils.format(now, "yyyy/MM/dd");
+    }
+    /**
+     * 日期路径 即年/月/日 如20180808
+     */
+    public static final String dateTime()
+    {
+        Date now = new Date();
+        return DateFormatUtils.format(now, "yyyyMMdd");
+    }
+
+    /**
+     * 日期型字符串转化为日期 格式
+     */
+    public static Date parseDate(Object str)
+    {
+        if (str == null)
+        {
+            return null;
+        }
+        try
+        {
+            return parseDate(str.toString(), parsePatterns);
+        }
+        catch (ParseException e)
+        {
+            return null;
+        }
+    }
+
+    /**
+     * 获取服务器启动时间
+     */
+    public static Date getServerStartDate()
+    {
+        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
+        return new Date(time);
+    }
+
+    /**
+     * 计算相差天数
+     */
+    public static int differentDaysByMillisecond(Date date1, Date date2)
+    {
+        return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
+    }
+
+    /**
+     * 计算时间差
+     *
+     * @param endDate 最后时间
+     * @param startTime 开始时间
+     * @return 时间差(天/小时/分钟)
+     */
+    public static String timeDistance(Date endDate, Date startTime)
+    {
+        long nd = 1000 * 24 * 60 * 60;
+        long nh = 1000 * 60 * 60;
+        long nm = 1000 * 60;
+        // long ns = 1000;
+        // 获得两个时间的毫秒时间差异
+        long diff = endDate.getTime() - startTime.getTime();
+        // 计算差多少天
+        long day = diff / nd;
+        // 计算差多少小时
+        long hour = diff % nd / nh;
+        // 计算差多少分钟
+        long min = diff % nd % nh / nm;
+        // 计算差多少秒//输出结果
+        // long sec = diff % nd % nh % nm / ns;
+        return day + "天" + hour + "小时" + min + "分钟";
+    }
+
+    /**
+     * 增加 LocalDateTime ==> Date
+     */
+    public static Date toDate(LocalDateTime temporalAccessor)
+    {
+        ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault());
+        return Date.from(zdt.toInstant());
+    }
+
+    /**
+     * 增加 LocalDate ==> Date
+     */
+    public static Date toDate(LocalDate temporalAccessor)
+    {
+        LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));
+        ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
+        return Date.from(zdt.toInstant());
+    }
+
+    // 返回过去7天的日期字符串列表,包含今天(自定义格式)
+    public static List<String> getPreviousSevenDays(String pattern) {
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
+        List<String> dateStrings = new ArrayList<>(7);
+        LocalDate today = LocalDate.now();
+        for (int i = 6; i >= 0; i--) {
+            dateStrings.add(today.minusDays(i).format(formatter));
+        }
+        return dateStrings;
+    }
+
+
+    /**
+     * 获取上个月年月
+     * @return
+     */
+    public static String getLastMonth(){
+        // 获取当前日期
+        LocalDate currentDate = LocalDate.now();
+
+        // 获取当前年份和上一个月份的组合(不包含具体的日)
+        YearMonth lastMonthYearMonth = YearMonth.from(currentDate).minusMonths(1);
+
+        return lastMonthYearMonth.toString();
+    }
+}