Explorar o código

Merge branch 'dev' of xiongzhu/zhumj into master

wangqifan %!s(int64=3) %!d(string=hai) anos
pai
achega
140fa509a7

+ 28 - 0
src/main/java/com/izouma/zhumj/dto/dailyReport/StoreCycleFee.java

@@ -0,0 +1,28 @@
+package com.izouma.zhumj.dto.dailyReport;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import io.swagger.annotations.ApiModel;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@ApiModel(value = "门店周期费用", description = "门店周期费用")
+@ExcelIgnoreUnannotated
+public class StoreCycleFee {
+    private String     storeName;
+    private String     name;
+    private String     feeType;
+    private String     roomName;
+    private String     bedName;
+    private LocalDate  settleDate;
+    private BigDecimal money;
+}

+ 2 - 0
src/main/java/com/izouma/zhumj/repo/PersonalFeeRepo.java

@@ -84,4 +84,6 @@ public interface PersonalFeeRepo extends JpaRepository<PersonalFee, Long>, JpaSp
     List<PersonalFee> findAllByStoreIdAndSettleTimeBetweenAndFreeIsTrue(Long storeId, LocalDateTime start, LocalDateTime end);
 
     List<PersonalFee> findAllByPayMethodAndSettleTimeBetween(PayMethod payMethod, LocalDateTime start, LocalDateTime end);
+
+    List<PersonalFee> findAllByStoreIdAndCycleStartDateNotNullOrderByName(Long storeId);
 }

+ 32 - 0
src/main/java/com/izouma/zhumj/service/PersonalFeeService.java

@@ -5,6 +5,7 @@ import com.izouma.zhumj.domain.sale.Contract;
 import com.izouma.zhumj.domain.sale.ContractStore;
 import com.izouma.zhumj.dto.PageQuery;
 import com.izouma.zhumj.dto.PersonalFeeDTO;
+import com.izouma.zhumj.dto.dailyReport.StoreCycleFee;
 import com.izouma.zhumj.dto.excel.DepositFeeDTO;
 import com.izouma.zhumj.dto.report.FeeReport;
 import com.izouma.zhumj.enums.*;
@@ -21,6 +22,7 @@ import com.izouma.zhumj.web.BaseController;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
+import org.reflections.Store;
 import org.springframework.beans.BeanUtils;
 import org.springframework.context.event.EventListener;
 import org.springframework.data.domain.Page;
@@ -661,4 +663,34 @@ public class PersonalFeeService {
         });
         return result;
     }
+
+    public List<StoreCycleFee> showStoreCycleFee(Long storeId) {
+        List<StoreCycleFee> result = new ArrayList<>();
+        List<PersonalFee> personalFees = personalFeeRepo.findAllByStoreIdAndCycleStartDateNotNullOrderByName(storeId);
+        Map<Long, List<Long>> feeRecord = new HashMap<>();
+        personalFees.forEach(personalFee -> {
+            List<Long> feeTypes = new ArrayList<>();
+            if (feeRecord.get(personalFee.getCheckinId()) != null) {
+                feeTypes = feeRecord.get(personalFee.getCheckinId());
+            }
+            if (!feeTypes.contains(personalFee.getPersonalFeeTypeId())) {
+                StoreCycleFee storeCycleFee = new StoreCycleFee();
+                storeCycleFee.setFeeType(personalFee.getPersonalFeeType().getName());
+                BedInfo bedInfo = bedInfoRepo.findById(personalFee.getBedId()).orElse(null);
+                RoomInfo roomInfo = roomInfoRepo.findById(personalFee.getRoomId()).orElse(null);
+                storeCycleFee.setBedName(Optional.ofNullable(bedInfo).orElse(BedInfo.builder().bedName("未查找到").build())
+                        .getBedName());
+                storeCycleFee
+                        .setBedName(Optional.ofNullable(roomInfo).orElse(RoomInfo.builder().roomName("未查找到").build())
+                                .getRoomName());
+                storeCycleFee.setMoney(personalFee.getMoney());
+                storeCycleFee.setSettleDate(personalFee.getSettleTime().toLocalDate());
+                storeCycleFee.setFeeType(personalFee.getPersonalFeeType().getName());
+                feeTypes.add(personalFee.getPersonalFeeTypeId());
+                feeRecord.put(personalFee.getCheckinId(), feeTypes);
+                result.add(storeCycleFee);
+            }
+        });
+        return result;
+    }
 }

+ 7 - 0
src/main/java/com/izouma/zhumj/web/PersonalFeeController.java

@@ -2,8 +2,10 @@ package com.izouma.zhumj.web;
 
 import com.izouma.zhumj.domain.IndividualRent;
 import com.izouma.zhumj.domain.PersonalFee;
+import com.izouma.zhumj.domain.StoreInfo;
 import com.izouma.zhumj.dto.PageQuery;
 import com.izouma.zhumj.dto.PersonalFeeDTO;
+import com.izouma.zhumj.dto.dailyReport.StoreCycleFee;
 import com.izouma.zhumj.dto.excel.DepositFeeDTO;
 import com.izouma.zhumj.dto.report.FeeReport;
 import com.izouma.zhumj.enums.PayMethod;
@@ -135,4 +137,9 @@ public class PersonalFeeController extends BaseController {
         }
         return personalFeeService.showRateCount(yearMonth);
     }
+
+    @GetMapping("/showCycleFee")
+    public List<StoreCycleFee> showCycleFee(Long storeId) {
+        return personalFeeService.showStoreCycleFee(storeId);
+    }
 }

+ 8 - 0
src/main/vue/src/router.js

@@ -2061,6 +2061,14 @@ const router = new Router({
                     meta: {
                         title: '周报'
                     }
+                },
+                {
+                    path: '/storeCycleReport',
+                    name: 'storeCycleReport',
+                    component: () => import(/* webpackChunkName: "storeCycleReport" */ '@/views/Report/StoreCycleFee.vue'),
+                    meta: {
+                        title: '周报'
+                    }
                 }
                 /**INSERT_LOCATION**/
             ]

+ 188 - 0
src/main/vue/src/views/Report/StoreCycleFee.vue

@@ -0,0 +1,188 @@
+<template>
+    <div class="list-view" v-loading="loading" :style="{ width: showSummary ? 'auto' : '100%' }">
+        <div class="filters-container">
+            <el-button type="primary" @click="getData">查询</el-button>
+            <el-button
+                @click="download()"
+                type="primary"
+                icon="el-icon-download"
+                :loading="downloading"
+                class="filter-item"
+            >
+                导出
+            </el-button>
+        </div>
+        <el-table
+            :data="tableData"
+            row-key="id"
+            ref="table"
+            header-row-class-name="table-header-row"
+            header-cell-class-name="table-header-cell"
+            row-class-name="table-row"
+            cell-class-name="table-cell"
+            v-loading="$store.state.fetchingData"
+            :height="tableHeight"
+            show-summary
+            :summary-method="getSummaries"
+        >
+            <el-table-column label="#" type="index" width="50"></el-table-column>
+            <el-table-column prop="roomName" label="房间名称"></el-table-column>
+            <el-table-column prop="bedName" label="床位名称"></el-table-column>
+            <el-table-column prop="name" label="个人名称"></el-table-column>
+            <el-table-column prop="feeType" label="费用类型"></el-table-column>
+            <el-table-column prop="money" label="费用总额"></el-table-column>
+            <el-table-column prop="settleTime" label="结算时间"></el-table-column>
+        </el-table>
+    </div>
+</template>
+<script>
+import pageableTable from '@/mixins/pageableTable';
+import { addMonths, format } from 'date-fns';
+import Qrcode from '@chenfengyuan/vue-qrcode';
+import PersonalFeeList from '@/components/roomStatus/PersonalFeeList';
+import PersonalFeeEdit from '@/components/operation/PersonalFeeEdit';
+import IndividualRentList from '@/components/operation/IndividualRentList';
+import CheckinInfoEdit from '@/components/operation/CheckinInfoEdit';
+
+export default {
+    components: {
+        IndividualRentList
+    },
+    name: 'storeIndividualReport',
+    mixins: [pageableTable],
+    data() {
+        return {
+            roomId: null,
+            search: '',
+            roomInfoOptions: [],
+            showSummary: false,
+            loading: false,
+            downloading: false,
+            tableData: [],
+            showRentDialog: false,
+            selectedCheckinId: null,
+            checkinStatusOptions: [
+                { value: 'in', label: '在住' },
+                { value: 'out', label: '退宿' }
+            ],
+            checkinStatus: ''
+        };
+    },
+    computed: {
+        selection() {
+            return this.$refs.table.selection.map(i => i.id);
+        }
+    },
+    methods: {
+        getSummaries(param) {
+            const { columns, data } = param;
+            const sums = [];
+            //循环处理所有列数据
+            columns.forEach((column, index) => {
+                if (index === 0) {
+                    sums[index] = '总数';
+                    return;
+                }
+                if (index === 1) {
+                    sums[index] = '';
+                    return;
+                }
+                if (index === 2) {
+                    sums[index] = '';
+                    return;
+                }
+                if (index === 3) {
+                    sums[index] = '';
+                    return;
+                }
+                if (index === 9 || index === 15) {
+                    const values = data.map(item => Number(item[column.property]));
+                    sums[index] =
+                        values.reduce((prev, curr) => {
+                            const value = Number(curr);
+                            if (!isNaN(value)) {
+                                return prev + curr;
+                            } else {
+                                return prev;
+                            }
+                        }, 0) / values.length;
+                    sums[index] = parseFloat(sums[index]).toFixed(2);
+                    return;
+                }
+                //将每列的所有数据数字化处理成一个数组
+                const values = data.map(item => Number(item[column.property]));
+                //当前列的所有数据全是数字类型时
+                if (!values.every(value => isNaN(value))) {
+                    //将当前列数据数组中的所有值,从左到右依次累加处理
+                    sums[index] = values.reduce((prev, curr) => {
+                        const value = Number(curr);
+                        if (!isNaN(value)) {
+                            return prev + curr;
+                        } else {
+                            return prev;
+                        }
+                    }, 0);
+                    sums[index] += '';
+                } else {
+                    sums[index] = 'N/A';
+                }
+            });
+
+            return sums;
+        },
+        beforeOnCreate() {
+            this.$http.get('/roomInfo/all', { size: 10000, query: { storeId: this.selectedStoreId } }).then(res => {
+                this.roomInfoOptions = res.content;
+            });
+        },
+        getData() {
+            this.loading = true;
+            this.$http
+                .get('/personalFee/showCycleFee', {
+                    storeId: this.selectedStoreId,
+                })
+                .then(res => {
+                    this.loading = false;
+                    this.tableData = res;
+                    this.showSummary = true;
+                })
+                .catch(e => {
+                    this.loading = false;
+                    this.$message.error(e.error);
+                });
+        },
+        download() {
+            this.downloading = true;
+            this.$axios
+                .get('/report/storeIndividualReportExcel', {
+                    params: {
+                        storeId: this.selectedStoreId,
+                        roomId: this.roomId,
+                        search: this.search,
+                        checkinStatus: this.checkinStatus
+                    },
+                    responseType: 'blob'
+                })
+                .then(res => {
+                    this.downloading = false;
+                    const downloadUrl = window.URL.createObjectURL(new Blob([res.data]));
+                    const link = document.createElement('a');
+                    link.href = downloadUrl;
+                    link.setAttribute(
+                        'download',
+                        decodeURIComponent(res.headers['content-disposition'].split('filename=')[1])
+                    );
+                    document.body.appendChild(link);
+                    link.click();
+                    link.remove();
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.downloading = false;
+                    this.$message.error(e.error);
+                });
+        }
+    }
+};
+</script>
+<style lang="less" scoped></style>