drew 5 лет назад
Родитель
Сommit
53e16b0de1

+ 11 - 0
db/delete_contract.sql

@@ -0,0 +1,11 @@
+delete from contract_bill;
+delete from contract_room_type;
+delete from contract_store;
+delete from phase_fixed_fee;
+delete from phase_free_fee;
+delete from phase_reserve_room;
+delete from phase_room_type;
+delete from phase_store;
+delete from contract_phase;
+delete from contract;
+

+ 6 - 0
src/main/java/com/izouma/zhumj/domain/sale/Contract.java

@@ -4,6 +4,7 @@ package com.izouma.zhumj.domain.sale;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.izouma.zhumj.annotations.Searchable;
 import com.izouma.zhumj.domain.BaseEntity;
+import com.izouma.zhumj.dto.ContractPhase;
 import com.izouma.zhumj.enums.*;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
@@ -166,6 +167,11 @@ public class Contract extends BaseEntity implements Serializable {
     @ApiModelProperty("账单")
     List<ContractBill> bills = new ArrayList<>();
 
+    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
+    @JoinColumn(name = "contractId")
+    @ApiModelProperty("合同期")
+    List<ContractPhase> phases;
+
     @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
     @JoinColumn(name = "contractId")
     @ApiModelProperty(value = "合同预定房型", name = "roomTypes")

+ 0 - 5
src/main/java/com/izouma/zhumj/domain/sale/PhaseRoomType.java

@@ -42,11 +42,6 @@ public class PhaseRoomType extends BaseEntity implements Serializable {
     @ApiModelProperty(value = "合同ID", name = "contractId")
     private Long phaseId;
 
-    @ApiModelProperty(value = "合同编号", name = "contractNumber")
-    @NotEmpty(message = "合同编号不能为空")
-    @Column(length = 50)
-    private String contractNumber;
-
     @ApiModelProperty("门店ID")
     private Long storeId;
 

+ 9 - 2
src/main/java/com/izouma/zhumj/dto/ContractPhase.java

@@ -11,6 +11,7 @@ import lombok.Data;
 import lombok.NoArgsConstructor;
 
 import javax.persistence.*;
+import java.math.BigDecimal;
 import java.time.LocalDateTime;
 import java.util.List;
 
@@ -34,11 +35,17 @@ public class ContractPhase extends BaseEntity {
     @ApiModelProperty("结束时间")
     private LocalDateTime endTime;
 
-    @ApiModelProperty("结束时间")
+    @ApiModelProperty("月份")
     private int months;
 
+    @ApiModelProperty("天数")
+    private int days;
+
+    @ApiModelProperty("月租金")
+    private BigDecimal monthlyRent;
+
     @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.DETACH)
-    @JoinColumn(name = "contractId")
+    @JoinColumn(name = "phaseId")
     @ApiModelProperty("绑定门店")
     private List<PhaseStore> stores;
 }

+ 8 - 0
src/main/java/com/izouma/zhumj/repo/sale/ContractPhaseRepo.java

@@ -0,0 +1,8 @@
+package com.izouma.zhumj.repo.sale;
+
+import com.izouma.zhumj.dto.ContractPhase;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+public interface ContractPhaseRepo extends JpaRepository<ContractPhase, Long>, JpaSpecificationExecutor<ContractPhase> {
+}

+ 8 - 0
src/main/java/com/izouma/zhumj/repo/sale/PhaseRoomTypeRepo.java

@@ -0,0 +1,8 @@
+package com.izouma.zhumj.repo.sale;
+
+import com.izouma.zhumj.domain.sale.PhaseRoomType;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+public interface PhaseRoomTypeRepo extends JpaRepository<PhaseRoomType, Long>, JpaSpecificationExecutor<PhaseRoomType> {
+}

+ 8 - 0
src/main/java/com/izouma/zhumj/repo/sale/PhaseStoreRepo.java

@@ -0,0 +1,8 @@
+package com.izouma.zhumj.repo.sale;
+
+import com.izouma.zhumj.domain.sale.PhaseStore;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+public interface PhaseStoreRepo extends JpaRepository<PhaseStore, Long>, JpaSpecificationExecutor<PhaseStore> {
+}

+ 35 - 17
src/main/java/com/izouma/zhumj/service/sale/ContractService.java

@@ -5,6 +5,7 @@ import com.izouma.zhumj.config.Constants;
 import com.izouma.zhumj.domain.*;
 import com.izouma.zhumj.domain.sale.*;
 import com.izouma.zhumj.dto.ContractCheckinInfo;
+import com.izouma.zhumj.dto.ContractPhase;
 import com.izouma.zhumj.dto.PageQuery;
 import com.izouma.zhumj.dto.sale.StoreContractDTO;
 import com.izouma.zhumj.enums.*;
@@ -52,23 +53,26 @@ import static com.izouma.zhumj.web.BaseController.toPredicates;
 @Slf4j
 public class ContractService {
 
-    private ContractRepo         contractRepo;
-    private CustomerService      customerService;
-    private CustomerRepo         customerRepo;
-    private ContractStaffRepo    staffRepo;
-    private ApplicationContext   applicationContext;
-    private ContractStoreRepo    contractStoreRepo;
-    private UserRepo             userRepo;
-    private CheckinInfoRepo      checkinInfoRepo;
-    private BedInfoRepo          bedInfoRepo;
-    private StoreNoticeRepo      storeNoticeRepo;
-    private DepartmentService    departmentService;
-    private ContractHistoryRepo  contractHistoryRepo;
-    private StoreInfoRepo        storeInfoRepo;
-    private RoomTypeInfoRepo     roomTypeInfoRepo;
-    private ContractRoomTypeRepo contractRoomTypeRepo;
-    private ContractBillRepo     contractBillRepo;
-    private BillDetailRepo       billDetailRepo;
+    private final ContractRepo         contractRepo;
+    private final CustomerService      customerService;
+    private final CustomerRepo         customerRepo;
+    private final ContractStaffRepo    staffRepo;
+    private final ApplicationContext   applicationContext;
+    private final ContractStoreRepo    contractStoreRepo;
+    private final UserRepo             userRepo;
+    private final CheckinInfoRepo      checkinInfoRepo;
+    private final BedInfoRepo          bedInfoRepo;
+    private final StoreNoticeRepo      storeNoticeRepo;
+    private final DepartmentService    departmentService;
+    private final ContractHistoryRepo  contractHistoryRepo;
+    private final StoreInfoRepo        storeInfoRepo;
+    private final RoomTypeInfoRepo     roomTypeInfoRepo;
+    private final ContractRoomTypeRepo contractRoomTypeRepo;
+    private final ContractBillRepo     contractBillRepo;
+    private final BillDetailRepo       billDetailRepo;
+    private final ContractPhaseRepo    contractPhaseRepo;
+    private final PhaseStoreRepo       phaseStoreRepo;
+    private final PhaseRoomTypeRepo    phaseRoomTypeRepo;
 
     public Page<Contract> all(PageQuery pageQuery, Integer contractType) {
         return contractRepo.findAll((Specification<Contract>) (root, criteriaQuery, criteriaBuilder) -> {
@@ -320,10 +324,24 @@ public class ContractService {
             bill.setTotal(contract.getBills().size());
         }
 
+        List<ContractPhase> phases = new ArrayList<>(contract.getPhases());
+        contract.getPhases().clear();
+
         //先保存 ContractStore,不然 ContractRoomType 的 contractId 会变成 null
         contractStoreRepo.saveAll(contract.getContractStoreList());
         contract = contractRepo.save(contract);
 
+        for (ContractPhase phase : phases) {
+            phase.setContractId(contract.getId());
+            List<PhaseStore> stores = new ArrayList<>(phase.getStores());
+            phase.getStores().clear();
+            contractPhaseRepo.save(phase);
+            for (PhaseStore store : stores) {
+                store.setPhaseId(phase.getId());
+            }
+            phaseStoreRepo.saveAll(stores);
+        }
+
         //如果是团散直接添加合同人员信息
         if (contract.getCheckInType().equals(CheckInType.INDIVIDUAL)) {
             if (!ObjectUtils.isEmpty(contract.getContactList())) {

+ 1 - 1
src/main/resources/application.yaml

@@ -12,7 +12,7 @@ spring:
 #        url: jdbc:mysql://rdsave1o67m1ido6gwp6public.mysql.rds.aliyuncs.com/zhu_meng_ju_test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2b8
 #        username: microball
 #        password: 2wsx@WSX#EDC
-        url: jdbc:mysql://121.40.132.44/zmj_test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2b8
+        url: jdbc:mysql://192.168.50.97/zmj_test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2b8
         username: root
         password: 3edc#EDC
         hikari:

+ 1 - 1
src/main/vue/package.json

@@ -19,7 +19,7 @@
     "clipboard": "^2.0.4",
     "core-js": "^2.6.5",
     "date-fns": "^2.3.0",
-    "element-ui": "^2.13.0",
+    "element-ui": "^2.13.1",
     "ip": "^1.1.5",
     "mathjs": "^6.6.0",
     "normalize.css": "^8.0.1",

+ 307 - 148
src/main/vue/src/views/sale/ContractEdit.vue

@@ -21,15 +21,13 @@
                         type="datetime"
                         value-format="yyyy-MM-dd HH:mm:ss"
                         placeholder="选择日期时间"
-                        @change="getContractDays"
                         default-time="00:00:00"
                     >
                     </el-date-picker>
                 </el-form-item>
 
                 <el-form-item prop="contractDays" label="合同期(月)">
-                    <el-input-number type="number" v-model="formData.contractMonthly" @change="getContractDays">
-                    </el-input-number>
+                    <el-input-number type="number" v-model="formData.contractMonthly"> </el-input-number>
                 </el-form-item>
 
                 <el-form-item prop="contractEndTime" label="合同结束时间">
@@ -38,7 +36,6 @@
                         type="datetime"
                         value-format="yyyy-MM-dd HH:mm:ss"
                         placeholder="选择日期时间"
-                        @change="getContractDaysOnly"
                     >
                     </el-date-picker>
                 </el-form-item>
@@ -88,7 +85,8 @@
                             v-for="(item, index) in formData.phases"
                             :name="index"
                             :key="index"
-                            :class="`phase-${index}-stores`"
+                            :class="`phase-stores phase-${index}-stores`"
+                            :phase-index="index"
                         >
                             <template slot="title">
                                 <span>{{ toChinesNum(index + 1) }}期绑定门店</span>
@@ -102,6 +100,14 @@
                                 >
                                     新增门店
                                 </el-button>
+                                <el-button
+                                    v-if="activeTab === index && index === formData.phases.length - 1"
+                                    size="mini"
+                                    type="danger"
+                                    @click.stop="removePhase(index)"
+                                >
+                                    删除合同期
+                                </el-button>
                                 <span class="phase-time">{{ item.startTime }} 至 {{ item.endTime }}</span>
                             </template>
                             <contract-store-choose
@@ -117,7 +123,7 @@
                         </el-collapse-item>
                     </el-collapse>
                 </el-form-item>
-                <el-button class="btn-add-phase" @click="onAddPhase">添加合同期</el-button>
+                <el-button class="btn-add-phase" @click="onAddPhase" type="primary" plain>添加合同期</el-button>
             </el-card>
 
             <el-card shadow="never">
@@ -606,76 +612,189 @@ export default {
             text: '',
             textarea: '',
             saleEdit: false, //disables 为false
+            // formData: {
+            //     bedsAmount: 0,
+            //     bet: 1,
+            //     checkInType: 'TEAM',
+            //     bills: [],
+            //     contactList: [],
+            //     contractStoreList: [],
+            //     monthlyRent: 0,
+            //     deposit: 0,
+            //     contractMonthly: 0,
+            //     contractDays: 0,
+            //     contractEndTime: '',
+            //     isInvoice: false,
+            //     brandId: null,
+            //     status: 'STAY_IN',
+            //     phases: []
+            // },
             formData: {
                 bedsAmount: 0,
                 bet: 1,
                 checkInType: 'TEAM',
-                bills: [],
-                contactList: [],
+                bills: [
+                    {
+                        idx: 1,
+                        dueTime: '2020-04-14 00:00:00',
+                        startTime: '2020-04-15 00:00:00',
+                        endTime: '2020-07-14 23:59:59',
+                        money: 4800,
+                        flowBet: 1200,
+                        status: 'NOT_PAID',
+                        type: 'PRE_PAID'
+                    },
+                    {
+                        idx: 2,
+                        dueTime: '2020-07-14 00:00:00',
+                        startTime: '2020-07-15 00:00:00',
+                        endTime: '2020-10-14 23:59:59',
+                        money: 3600,
+                        flowBet: null,
+                        status: 'NOT_PAID',
+                        type: 'PRE_PAID'
+                    },
+                    {
+                        idx: 3,
+                        dueTime: '2020-10-14 00:00:00',
+                        startTime: '2020-10-15 00:00:00',
+                        endTime: '2021-01-14 23:59:59',
+                        money: 3600,
+                        flowBet: null,
+                        status: 'NOT_PAID',
+                        type: 'PRE_PAID'
+                    },
+                    {
+                        idx: 4,
+                        dueTime: '2021-01-14 00:00:00',
+                        startTime: '2021-01-15 00:00:00',
+                        endTime: '2021-04-14 23:59:59',
+                        money: 3600,
+                        flowBet: null,
+                        status: 'NOT_PAID',
+                        type: 'PRE_PAID'
+                    },
+                    {
+                        idx: 5,
+                        dueTime: '2022-04-14 00:00:00',
+                        startTime: '2022-04-15 00:00:00',
+                        endTime: '2022-04-14 23:59:59',
+                        money: 4320,
+                        flowBet: null,
+                        status: 'NOT_PAID',
+                        type: 'PRE_PAID'
+                    },
+                    {
+                        idx: 6,
+                        dueTime: '2022-07-14 00:00:00',
+                        startTime: '2022-07-15 00:00:00',
+                        endTime: '2022-04-14 23:59:59',
+                        money: 4320,
+                        flowBet: null,
+                        status: 'NOT_PAID',
+                        type: 'PRE_PAID'
+                    },
+                    {
+                        idx: 7,
+                        dueTime: '2022-10-14 00:00:00',
+                        startTime: '2022-10-15 00:00:00',
+                        endTime: '2022-04-14 23:59:59',
+                        money: 4320,
+                        flowBet: null,
+                        status: 'NOT_PAID',
+                        type: 'PRE_PAID'
+                    },
+                    {
+                        idx: 8,
+                        dueTime: '2023-01-14 00:00:00',
+                        startTime: '2023-01-15 00:00:00',
+                        endTime: '2022-04-14 23:59:59',
+                        money: 4320,
+                        flowBet: null,
+                        status: 'NOT_PAID',
+                        type: 'PRE_PAID'
+                    }
+                ],
+                contactList: [{ name: '李先生', mobile: '13816895681' }],
                 contractStoreList: [],
-                monthlyRent: 0,
+                monthlyRent: 1200,
                 deposit: 0,
-                contractMonthly: 0,
+                contractMonthly: 24,
                 contractDays: 0,
-                contractEndTime: '',
+                contractEndTime: '2022-04-14 23:59:59',
                 isInvoice: false,
-                brandId: null,
+                brandId: 86552,
                 status: 'STAY_IN',
                 phases: [
                     {
-                        startTime: '2020-04-14 00:00:00',
+                        startTime: '2020-04-15 00:00:00',
                         months: 12,
-                        endTime: '2021-04-13 23:59:59',
+                        endTime: '2021-04-14 23:59:59',
                         stores: [
                             {
-                                storeId: 433,
+                                storeId: 1536,
                                 freeFeeTypes: [],
                                 roomTypeInfo: [],
                                 fixedFeeTypes: [],
-                                roomTypes: [],
-                                roomTypeDesc: '',
-                                storeName: '托乐嘉门店'
-                            },
-                            {
-                                storeId: 2418,
-                                freeFeeTypes: [],
-                                roomTypeInfo: [],
-                                fixedFeeTypes: [],
-                                roomTypes: [],
-                                roomTypeDesc: '',
-                                storeName: '筑梦居公寓闵行吴中路店'
-                            },
-                            { storeId: '', freeFeeTypes: [], roomTypeInfo: [], fixedFeeTypes: [], roomTypes: [] }
+                                roomTypes: [
+                                    {
+                                        key: 1586933090017,
+                                        storeId: 1536,
+                                        contractRoomInfoList: [],
+                                        beds: 12,
+                                        price: 100,
+                                        roomTypeName: '8人间',
+                                        roomTypeId: 1541
+                                    }
+                                ],
+                                roomTypeDesc: '12间8人间',
+                                storeName: '筑梦居公寓闵行古美店'
+                            }
                         ]
                     },
                     {
-                        startTime: '2021-04-14 00:00:00',
+                        startTime: '2021-04-15 00:00:00',
                         disableStart: true,
                         months: 12,
-                        endTime: '2022-04-13 23:59:59',
+                        endTime: '2022-04-14 23:59:59',
                         stores: [
                             {
-                                storeId: 3123,
-                                freeFeeTypes: [],
-                                roomTypeInfo: [],
-                                fixedFeeTypes: [],
-                                roomTypes: [],
-                                roomTypeDesc: '',
-                                storeName: '筑梦居公寓浦东张江店'
-                            },
-                            {
-                                storeId: 4232,
+                                storeId: 1536,
                                 freeFeeTypes: [],
                                 roomTypeInfo: [],
                                 fixedFeeTypes: [],
-                                roomTypes: [],
-                                roomTypeDesc: '',
-                                storeName: '筑梦居公寓闵行万象城店'
-                            },
-                            { storeId: '', freeFeeTypes: [], roomTypeInfo: [], fixedFeeTypes: [], roomTypes: [] }
+                                roomTypes: [
+                                    {
+                                        key: 1586933102367,
+                                        storeId: 1536,
+                                        contractRoomInfoList: [],
+                                        beds: 12,
+                                        price: 120,
+                                        roomTypeName: '8人间',
+                                        roomTypeId: 1541
+                                    }
+                                ],
+                                roomTypeDesc: '12间8人间',
+                                storeName: '筑梦居公寓闵行古美店'
+                            }
                         ]
                     }
-                ]
+                ],
+                contractTotalRent: 31680,
+                flowBet: 1200,
+                advancePayment: 1,
+                contractNumber: 'sdfsadf',
+                contractBeginTime: '2020-04-15 00:00:00',
+                pay: '3',
+                customerId: 9897,
+                customerSource: 'GROUND_PUSH',
+                customerIndustry: '中式餐饮',
+                contactAddress: '上海市普陀区宁夏路370号',
+                saleId: 417,
+                saleName: '张贇',
+                departmentId: 123923182,
+                departmentName: '销售3组',
+                contractSource: 'NEW_SIGN'
             },
             lastFlowBet: 0,
             rules: {
@@ -688,36 +807,7 @@ export default {
                 contractStoreList: [
                     {
                         validator: (rule, value, callback) => {
-                            if (!value || value.length === 0) {
-                                callback(new Error('请添加门店信息'));
-                            } else {
-                                Promise.all([
-                                    ...this.$refs.contractStoreChoose.map(ref => ref.valid()),
-                                    new Promise((resolve, reject) => {
-                                        let dict = {};
-                                        let error = null;
-                                        for (let contractStore of this.formData.contractStoreList) {
-                                            if (dict[contractStore.storeId]) {
-                                                error = '不能添加相同的门店';
-                                                break;
-                                            } else {
-                                                dict[contractStore.storeId] = true;
-                                            }
-                                        }
-                                        if (error) {
-                                            reject(error);
-                                        } else {
-                                            resolve();
-                                        }
-                                    })
-                                ])
-                                    .then(() => {
-                                        callback();
-                                    })
-                                    .catch(err => {
-                                        callback(new Error(err || '门店信息有误'));
-                                    });
-                            }
+                            callback();
                         }
                     }
                 ],
@@ -840,24 +930,28 @@ export default {
         };
     },
     computed: {
-        monthMoney() {
-            var money = 0;
-            var list = [...this.formData.contractStoreList];
-            list.forEach(item => {
-                var roomTypes = item.roomTypes;
-                roomTypes.forEach(room => {
-                    if (room.beds && room.price) {
-                        money = this.Add(money, this.Mul(room.beds, room.price));
-                    }
+        phaseMonthlyRent() {
+            return this.formData.phases.map(phase => {
+                let money = 0;
+                phase.stores.forEach(store => {
+                    store.roomTypes.forEach(roomType => {
+                        money += (roomType.price || 0) * (roomType.beds || 0);
+                    });
                 });
+                return money;
             });
-            return money;
+        },
+        monthlyRent() {
+            if (this.checkInType === 'TEAM_POST_PAID') return 0;
+            if (this.phaseMonthlyRent[0]) return this.phaseMonthlyRent[0];
+            return 0;
         },
         totalMoney() {
-            var money = 0;
-            if (this.formData.monthlyRent && this.formData.contractMonthly) {
-                money = this.Add(money, this.Mul(this.formData.monthlyRent, this.formData.contractMonthly));
-            }
+            if (this.checkInType === 'TEAM_POST_PAID') return 0;
+            let money = 0;
+            this.formData.phases.forEach((phase, index) => {
+                money += phase.months * this.phaseMonthlyRent[index];
+            });
             return money;
         },
         storeName() {
@@ -873,8 +967,8 @@ export default {
         }
     },
     watch: {
-        monthMoney() {
-            this.formData.monthlyRent = this.monthMoney;
+        monthlyRent() {
+            this.formData.monthlyRent = this.monthlyRent;
         },
         totalMoney() {
             this.formData.contractTotalRent = this.totalMoney;
@@ -957,18 +1051,106 @@ export default {
                 });
         },
         calcBills() {
-            if (!this.formData.contractBeginTime) {
-                this.$message.error('请输入合同开始时间');
+            if (!this.formData.phases.length) {
+                this.$message.error('请添加合同期');
+                return;
+            }
+            for (let i = 0; i < this.formData.phases.length; i++) {
+                if (!this.formData.phases[i].stores.length) {
+                    this.$message.error('请添加' + this.toChinesNum(i + 1) + '期门店信息');
+                    return;
+                }
+            }
+            if (this.formData.checkInType === 'TEAM' || this.formData.checkInType === 'SCATTERED_BEDS') {
+                if (isNaN(Number(this.formData.bet))) {
+                    this.$message.error('请输入押几');
+                    return;
+                }
+                if (isNaN(Number(this.formData.pay))) {
+                    this.$message.error('请输入付几');
+                    return;
+                }
+                if (!this.formData.advancePayment) {
+                    this.$message.error('请输入提前几天收款');
+                    return;
+                }
+            }
+            if (isNaN(Number(this.formData.flowBet))) {
+                this.$message.error('请输入押金');
                 return;
             }
-            if (!this.formData.contractMonthly) {
-                this.$message.error('请输入合同期');
+            if (this.formData.contractBeginTime > this.formData.contractEndTime) {
+                this.$message.error('合同结束时间必须大于开始时间');
                 return;
             }
-            if (!this.formData.contractEndTime) {
-                this.$message.error('请输入合同结束时间');
+
+            let bills = [];
+            let idx = 0;
+            const pay = Number(this.formData.pay);
+
+            if (this.formData.checkInType == 'TEAM' || this.formData.checkInType == 'SCATTERED_BEDS') {
+                for (let i = 0; i < this.formData.phases.length; i++) {
+                    const phase = this.formData.phases[i];
+                    let totalMonth = phase.months;
+                    const contractBeginTime = parseDate(phase.startTime);
+                    const contractEndTime = parseDate(phase.endTime);
+                    while (totalMonth > 0) {
+                        let startTime = addMonths(contractBeginTime, pay * idx);
+                        let endTime = addMonths(startTime, pay);
+                        let dueTime = addDays(startTime, -this.formData.advancePayment);
+                        if (isAfter(endTime, contractEndTime)) {
+                            endTime = contractEndTime;
+                        } else {
+                            endTime = addSeconds(endTime, -1);
+                        }
+                        let month = totalMonth - pay <= 0 ? totalMonth : pay;
+                        let money = month * this.phaseMonthlyRent[i];
+                        if (idx === 0) {
+                            money += this.formData.flowBet - this.lastFlowBet;
+                        }
+                        bills.push({
+                            idx: ++idx,
+                            dueTime: formatDate(dueTime),
+                            startTime: formatDate(startTime),
+                            endTime: formatDate(endTime),
+                            money: money,
+                            flowBet: idx === 1 ? this.formData.flowBet - this.lastFlowBet : null,
+                            status: 'NOT_PAID',
+                            type: 'PRE_PAID'
+                        });
+                        totalMonth = Math.max(0, totalMonth - pay);
+                    }
+                }
+                this.$set(this.formData, 'bills', bills);
+            } else {
+                let startTime = startOfDay(startOfMonth(contractBeginTime));
+                for (let i = 0; i < this.formData.contractMonthly + 1; i++) {
+                    bills.push({
+                        idx: i + 1,
+                        startTime: formatDate(startTime),
+                        endTime: formatDate(endOfDay(endOfMonth(startTime))),
+                        dueTime: formatDate(addMonths(startTime, 1)),
+                        money: null,
+                        flowBet: i === 0 ? this.formData.flowBet - this.lastFlowBet : null,
+                        status: 'PENDING',
+                        type: 'POST_PAID'
+                    });
+                }
+                startTime = addMonths(startTime, 1);
+                this.$set(this.formData, 'bills', bills);
+            }
+        },
+        calcBillsBak() {
+            if (!this.formData.phases.length) {
+                this.$message.error('请添加合同期');
                 return;
             }
+            for (let i = 0; i < this.formData.phases.length; i++) {
+                if (!this.formData.phases[i].stores.length) {
+                    this.$message.error('请添加' + this.toChinesNum(i + 1) + '期门店信息');
+                    return;
+                }
+            }
             if (this.formData.checkInType === 'TEAM' || this.formData.checkInType === 'SCATTERED_BEDS') {
                 if (isNaN(Number(this.formData.bet))) {
                     this.$message.error('请输入押几');
@@ -992,11 +1174,11 @@ export default {
                 return;
             }
 
+            let bills = [];
+            let idx = 0;
             let pay = Number(this.formData.pay);
             let contractBeginTime = parseDate(this.formData.contractBeginTime);
             let contractEndTime = parseDate(this.formData.contractEndTime);
-            let bills = [];
-            let idx = 0;
             let totalMonth = this.formData.contractMonthly;
             if (this.formData.checkInType == 'TEAM' || this.formData.checkInType == 'SCATTERED_BEDS') {
                 while (totalMonth > 0) {
@@ -1044,49 +1226,6 @@ export default {
                 this.$set(this.formData, 'bills', bills);
             }
         },
-        //获取合同时长
-        getContractDays() {
-            if (this.formData.contractBeginTime && this.formData.contractMonthly) {
-                this.formData.contractEndTime = formatDate(
-                    addSeconds(addMonths(parseDate(this.formData.contractBeginTime), this.formData.contractMonthly), -1)
-                );
-                this.formData.contractDays = differenceInCalendarDays(
-                    addSeconds(parseDate(this.formData.contractEndTime), 1),
-                    parseDate(this.formData.contractBeginTime)
-                );
-            }
-            //   if (!this.formData.contractMonthly) {
-            //     this.$message.error('请输入合同(月)');
-            //     return;
-            //   }
-
-            //   if (!this.formData.contractBeginTime) {
-            //     this.$message.error('请输入合同开始时间');
-            //     return;
-            //   }
-            //   (this.formData.contractEndTime = this.dateFormat(
-            //     'YYYY-mm-dd HH:MM:SS',
-            //     new Date().setMonth(
-            //       new Date(this.formData.contractBeginTime).getMonth() +
-            //         parseInt(this.formData.contractMonthly)
-            //     )
-            //   )),
-            //     (this.formData.contractDays = this.difference(
-            //       this.formData.contractBeginTime,
-            //       this.formData.contractEndTime
-            //     ));
-        },
-        getContractDaysOnly() {
-            if (this.formData.contractBeginTime && this.formData.contractBeginTime) {
-                this.formData.contractDays = differenceInCalendarDays(
-                    addSeconds(parseDate(this.formData.contractEndTime), 1),
-                    parseDate(this.formData.contractBeginTime)
-                );
-            }
-        },
-        /**
-         * 获取两个时间相差的天数
-         * */
         difference(beginTime, endTime) {
             console.log('difference', beginTime, endTime);
             var dateBegin = new Date(beginTime);
@@ -1161,7 +1300,7 @@ export default {
                 });
         },
         addPhaseStore(index) {
-            this.validPhaseStores(index)
+            (this.formData.phases[index].stores.length ? this.validPhaseStores(index) : Promise.resolve())
                 .then(res => {
                     this.formData.phases[index].stores.push({
                         storeId: '',
@@ -1175,7 +1314,9 @@ export default {
                         el && el.scrollTo({ left: 100000, behavior: 'smooth' });
                     });
                 })
-                .catch(e => {});
+                .catch(e => {
+                    console.log(e);
+                });
         },
         validPhaseStores(i) {
             return new Promise((resolve, reject) => {
@@ -1197,6 +1338,9 @@ export default {
                     });
             });
         },
+        removePhase(index) {
+            this.formData.phases.splice(index, 1);
+        },
         removeContractStore(index) {
             this.formData.contractStoreList.splice(index, 1);
         },
@@ -1259,7 +1403,7 @@ export default {
             return label;
         },
         onSave() {
-            this.$refs.form.validate(valid => {
+            this.$refs.form.validate((valid, fields) => {
                 if (valid) {
                     this.contractHistory = {
                         saveHistory: this.formData.id ? null : false,
@@ -1267,6 +1411,7 @@ export default {
                     };
                     this.showSaveDialog = true;
                 } else {
+                    console.log(fields);
                     this.$message.error('表单有误,请修改后重新提交');
                     return false;
                 }
@@ -1371,7 +1516,9 @@ export default {
                     }
                     this.showPhaseDialog = true;
                 })
-                .catch(i => {});
+                .catch(i => {
+                    console.log(i);
+                });
         },
         addPhase() {
             this.$refs.phaseForm.validate(valid => {
@@ -1379,6 +1526,18 @@ export default {
                     this.formData.phases.push({ ...this.phaseForm, stores: [] });
                     this.showPhaseDialog = false;
                     this.activeTab = this.formData.phases.length - 1;
+
+                    this.$set(this.formData, 'contractBeginTime', this.formData.phases[0].startTime);
+                    this.$set(
+                        this.formData,
+                        'contractEndTime',
+                        this.formData.phases[this.formData.phases.length - 1].endTime
+                    );
+                    this.$set(
+                        this.formData,
+                        'contractMonthly',
+                        this.formData.phases.map(i => i.months).reduce((a, b) => a + b, 0)
+                    );
                 }
             });
         },

+ 4 - 4
src/main/vue/yarn.lock

@@ -3343,10 +3343,10 @@ element-resize-detector@^1.1.10:
   dependencies:
     batch-processor "^1.0.0"
 
-element-ui@^2.13.0:
-  version "2.13.0"
-  resolved "https://registry.npm.taobao.org/element-ui/download/element-ui-2.13.0.tgz#f6bb04e5b0a76ea5f62466044b774407ba4ebd2d"
-  integrity sha1-9rsE5bCnbqX2JGYES3dEB7pOvS0=
+element-ui@^2.13.1:
+  version "2.13.1"
+  resolved "https://registry.npm.taobao.org/element-ui/download/element-ui-2.13.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Felement-ui%2Fdownload%2Felement-ui-2.13.1.tgz#0cb1a45cf27aa61c601defbe192740ac5cb9df7c"
+  integrity sha1-DLGkXPJ6phxgHe++GSdArFy533w=
   dependencies:
     async-validator "~1.8.1"
     babel-helper-vue-jsx-merge-props "^2.0.0"

+ 7 - 3
src/test/java/com/izouma/zhumj/CommonTest.java

@@ -325,8 +325,12 @@ public class CommonTest {
 
     @Test
     public void bigDecimalToString() {
-        LocalDateTime date = LocalDateTime.now();
-        System.out.println(date.with(DayOfWeek.MONDAY));
-        System.out.println(date.with(DayOfWeek.SUNDAY));
+        List<String> list1 = new ArrayList<>();
+        list1.add("1");
+        list1.add("2");
+        List<String> list2 = new ArrayList<>(list1);
+        list1.clear();
+        System.out.println(list1);
+        System.out.println(list2);
     }
 }