diff --git a/cjy-project/src/main/java/com/cjy/happyToEnjoy/util/SignUtil.java b/cjy-project/src/main/java/com/cjy/happyToEnjoy/util/SignUtil.java deleted file mode 100644 index 9e567402..00000000 --- a/cjy-project/src/main/java/com/cjy/happyToEnjoy/util/SignUtil.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.cjy.happyToEnjoy.util; - -import java.security.MessageDigest; -import java.util.Arrays; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -/** - * @author liangjiawei - * @createDate 2023/8/21 - */ -public class SignUtil { - - public static String getSign(Map data) { - Set keySet = data.keySet(); - String[] keyArr = keySet.toArray(new String[keySet.size()]); - Arrays.sort(keyArr); - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < keyArr.length; i++) { - String key = keyArr[i]; - sb.append(key + "=" + data.get(key)); - if (i != keyArr.length - 1) { - sb.append('&'); - } - } - try { - return string2MD5(sb.toString()).toLowerCase(); - } catch (Exception e) { - e.printStackTrace(); - } - return ""; - } - - - - public static String string2MD5(String inStr) { - MessageDigest md5 = null; - try { - md5 = MessageDigest.getInstance("MD5"); - } catch (Exception e) { - e.printStackTrace(); - return ""; - } - char[] charArray = inStr.toCharArray(); - byte[] byteArray = new byte[charArray.length]; - - for (int i = 0; i < charArray.length; i++) - byteArray[i] = (byte) charArray[i]; - byte[] md5Bytes = md5.digest(byteArray); - StringBuffer hexValue = new StringBuffer(); - for (int i = 0; i < md5Bytes.length; i++) { - int val = ((int) md5Bytes[i]) & 0xff; - if (val < 16) - hexValue.append("0"); - hexValue.append(Integer.toHexString(val)); - } - return hexValue.toString(); - - } -} diff --git a/cjy-project/src/main/java/com/cjy/happytoenjoy/domain/HappyToEnjoyEntity.java b/cjy-project/src/main/java/com/cjy/happytoenjoy/domain/HappyToEnjoyEntity.java new file mode 100644 index 00000000..95dae63d --- /dev/null +++ b/cjy-project/src/main/java/com/cjy/happytoenjoy/domain/HappyToEnjoyEntity.java @@ -0,0 +1,143 @@ +package com.cjy.happytoenjoy.domain; + +/** + * @author liangjiawei + * @createDate 2023/8/22 + */ +public class HappyToEnjoyEntity { + private String id; + private String scenicName; + private String name; + private String certificateType; + private String certificateCode; + private String phone; + private String carryFlag; + private String status; + private String reservationDate; + private String beginTime; + private String endingTime; + private String scanTime; + private String reservationNum; + private String exitStatus; + private String exitTime; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getScenicName() { + return scenicName; + } + + public void setScenicName(String scenicName) { + this.scenicName = scenicName; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCertificateType() { + return certificateType; + } + + public void setCertificateType(String certificateType) { + this.certificateType = certificateType; + } + + public String getCertificateCode() { + return certificateCode; + } + + public void setCertificateCode(String certificateCode) { + this.certificateCode = certificateCode; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public String getCarryFlag() { + return carryFlag; + } + + public void setCarryFlag(String carryFlag) { + this.carryFlag = carryFlag; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getReservationDate() { + return reservationDate; + } + + public void setReservationDate(String reservationDate) { + this.reservationDate = reservationDate; + } + + public String getBeginTime() { + return beginTime; + } + + public void setBeginTime(String beginTime) { + this.beginTime = beginTime; + } + + public String getEndingTime() { + return endingTime; + } + + public void setEndingTime(String endingTime) { + this.endingTime = endingTime; + } + + public String getScanTime() { + return scanTime; + } + + public void setScanTime(String scanTime) { + this.scanTime = scanTime; + } + + public String getReservationNum() { + return reservationNum; + } + + public void setReservationNum(String reservationNum) { + this.reservationNum = reservationNum; + } + + public String getExitStatus() { + return exitStatus; + } + + public void setExitStatus(String exitStatus) { + this.exitStatus = exitStatus; + } + + public String getExitTime() { + return exitTime; + } + + public void setExitTime(String exitTime) { + this.exitTime = exitTime; + } +} diff --git a/cjy-project/src/main/java/com/cjy/happytoenjoy/task/GetHappyToEnjoyTask.java b/cjy-project/src/main/java/com/cjy/happytoenjoy/task/GetHappyToEnjoyTask.java new file mode 100644 index 00000000..b3d94980 --- /dev/null +++ b/cjy-project/src/main/java/com/cjy/happytoenjoy/task/GetHappyToEnjoyTask.java @@ -0,0 +1,130 @@ +package com.cjy.happytoenjoy.task; + + +import com.alibaba.fastjson2.JSONObject; +import com.cjy.happytoenjoy.domain.HappyToEnjoyEntity; +import com.cjy.happytoenjoy.util.SignUtil; +import com.cjy.media.util.WeiBoEncryption; +import com.cjy.reservationdata.domain.AppointmentCenterData; +import com.cjy.reservationdata.service.IAppointmentCenterDataService; +import com.ruoyi.common.utils.DateUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; + +/** + * @author liangjiawei + * @createDate 2023/8/21 + */ + +@Component("GetHappyToEnjoyTask") +public class GetHappyToEnjoyTask { + @Value("${lxj.scenicId}") + private String scenicId; + + @Value("${lxj.appId}") + private String appId; + + @Value("${lxj.appSecret}") + private String appSecret; + + @Value("${lxj.numberOfDaysAvailable}") + private Integer numberOfDaysAvailable; + @Value("${weibo.encryptionRule}") + private String rule; + @Autowired + IAppointmentCenterDataService iAppointmentCenterDataService; + + //这里身份证、手机号继续加密 避免查询的时候无法解密 +// @Scheduled(cron = "0 0/1 * * * ?") + public void getEnjoymentAppointmentRecord() { + String timestamp = SignUtil.create_timestamp(); + String nonceStr = SignUtil.create_nonce_str(); + Map signDatgaMap = new HashMap<>(); + signDatgaMap.put("appId", appId); + signDatgaMap.put("timestamp", timestamp); + signDatgaMap.put("nonceStr", nonceStr); + signDatgaMap.put("appSecret", appSecret); + String sign = SignUtil.getSign(signDatgaMap); + signDatgaMap.put("sign", sign); + + String startDate = DateUtils.getDaysTimeToString(0); + String endDate = DateUtils.getDaysTimeToString(numberOfDaysAvailable); + JSONObject jo = new JSONObject(); + jo.put("scenicId", scenicId); + jo.put("startDate", startDate); + jo.put("endDate", endDate); + String responseSting = SignUtil.post("https://traveline.hebeitour.com.cn/api/reservation/getReservationRecordT", jo.toString(), signDatgaMap); + JSONObject jsonData = JSONObject.parseObject(responseSting); + List list = jsonData.getJSONArray("data").toList(HappyToEnjoyEntity.class); + List saveList =new ArrayList<>(); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd"); + list.stream().forEach(item->{ + AppointmentCenterData appointmentCenterData= new AppointmentCenterData(); + //预约日期 + try { + appointmentCenterData.setAppointmentDate(sdfDate.parse(item.getReservationDate())); + } catch (ParseException e) { + e.printStackTrace(); + } + //预约人姓名 + appointmentCenterData.setAppointmentPeopleName(item.getName()); + //预约人手机号 + appointmentCenterData.setAppointmentPeoplePhone(WeiBoEncryption.encrypt(item.getPhone(), rule)); + //预约时间段 + appointmentCenterData.setAppointmentSlot(item.getBeginTime()+"~"+item.getEndingTime()); + //证件类型 + if(item.getCertificateType().equals("身份证")){ + appointmentCenterData.setCertificateType("5501"); + //身份证号码 + appointmentCenterData.setDocumentsNumber(WeiBoEncryption.encrypt(item.getCertificateCode(), rule)); + }else { + appointmentCenterData.setCertificateType("5502"); + appointmentCenterData.setDocumentsNumber(item.getCertificateCode()); + } + + //状态 + if(item.getStatus().equals("2")){ + appointmentCenterData.setState("3"); + }else { + appointmentCenterData.setState(item.getStatus()); + } + + //核销时间 + try { + if(item.getScanTime() !=null){ + appointmentCenterData.setWriteOffTime( sdf.parse(item.getScanTime())); + } + + } catch (ParseException e) { + e.printStackTrace(); + } + // + appointmentCenterData.setSourceDataId(item.getId()); + appointmentCenterData.setSourceType(1); + appointmentCenterData.setExternalId("783232818342789120"); + appointmentCenterData.setDataSources("2"); + appointmentCenterData.setCreateTime(new Date()); + appointmentCenterData.setOrganCode(123L); + if(saveList.size()<1000){ + saveList.add(appointmentCenterData); + }else { + iAppointmentCenterDataService.synchronousData(saveList); + saveList.clear(); + saveList.add(appointmentCenterData); + } + + }); + if(!saveList.isEmpty()){ + iAppointmentCenterDataService.synchronousData(saveList); + } + + } + +} diff --git a/cjy-project/src/main/java/com/cjy/happyToEnjoy/task/GetHappyToEnjoyTask.java b/cjy-project/src/main/java/com/cjy/happytoenjoy/util/SignUtil.java similarity index 75% rename from cjy-project/src/main/java/com/cjy/happyToEnjoy/task/GetHappyToEnjoyTask.java rename to cjy-project/src/main/java/com/cjy/happytoenjoy/util/SignUtil.java index 852e61cb..749c49db 100644 --- a/cjy-project/src/main/java/com/cjy/happyToEnjoy/task/GetHappyToEnjoyTask.java +++ b/cjy-project/src/main/java/com/cjy/happytoenjoy/util/SignUtil.java @@ -1,7 +1,4 @@ -package com.cjy.happyToEnjoy.task; - -import com.alibaba.fastjson2.JSONObject; -import com.cjy.happyToEnjoy.util.SignUtil; +package com.cjy.happytoenjoy.util; import java.io.BufferedReader; import java.io.IOException; @@ -10,36 +7,16 @@ import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.URL; import java.security.MessageDigest; -import java.util.*; +import java.util.Arrays; +import java.util.Map; +import java.util.Set; +import java.util.UUID; /** * @author liangjiawei * @createDate 2023/8/21 */ -//scenic_id:1273900661162905602 -// app_id:app1668821827566313474 -// app_secret:8d5695249b71421cac834517b568c141 -public class GetHappyToEnjoyTask { - public static void main(String[] args) { - - - String timestamp = create_timestamp(); - String nonceStr = create_nonce_str(); - Map signDatgaMap = new HashMap<>(); - signDatgaMap.put("appId", "app1668821827566313474"); - signDatgaMap.put("timestamp", timestamp); - signDatgaMap.put("nonceStr", nonceStr); - signDatgaMap.put("appSecret", "8d5695249b71421cac834517b568c141"); - String sign = getSign(signDatgaMap); - signDatgaMap.put("sign", sign); - - JSONObject jo=new JSONObject(); - jo.put("scenicId", "1273900661162905602"); - jo.put("startDate", "2023-08-23"); - jo.put("endDate", "2023-08-23"); - System.out.println(signDatgaMap); - System.out.println(post("https://traveline.hebeitour.com.cn/api/reservation/getReservationRecordT", jo.toString(),signDatgaMap)); - } +public class SignUtil { public static String getSign(Map data) { Set keySet = data.keySet(); String[] keyArr = keySet.toArray(new String[keySet.size()]); diff --git a/cjy-project/src/main/java/com/cjy/parking/domain/ParkingTurnoverData.java b/cjy-project/src/main/java/com/cjy/parking/domain/ParkingTurnoverData.java index 30d3c103..57cf62ed 100644 --- a/cjy-project/src/main/java/com/cjy/parking/domain/ParkingTurnoverData.java +++ b/cjy-project/src/main/java/com/cjy/parking/domain/ParkingTurnoverData.java @@ -141,7 +141,23 @@ public class ParkingTurnoverData extends BaseEntity { //占用车位 private int occupyParkingSpace; - public String getVehicleAttributionId() { + public int getOccupyParkingSpace() { + return occupyParkingSpace; + } + + public void setOccupyParkingSpace(int occupyParkingSpace) { + this.occupyParkingSpace = occupyParkingSpace; + } + + public int getRemainingParkingSpace() { + return remainingParkingSpace; + } + + public void setRemainingParkingSpace(int remainingParkingSpace) { + this.remainingParkingSpace = remainingParkingSpace; + } + + public String getVehicleAttributionId() { return vehicleAttributionId; } diff --git a/cjy-project/src/main/java/com/cjy/parking/mapper/ParkingTurnoverDataMapper.java b/cjy-project/src/main/java/com/cjy/parking/mapper/ParkingTurnoverDataMapper.java index 38af2300..3106be1c 100644 --- a/cjy-project/src/main/java/com/cjy/parking/mapper/ParkingTurnoverDataMapper.java +++ b/cjy-project/src/main/java/com/cjy/parking/mapper/ParkingTurnoverDataMapper.java @@ -118,6 +118,7 @@ public interface ParkingTurnoverDataMapper * @return */ int updateParkingLotParkingSpaceInfoCount(ParkingTurnoverData parkingTurnoverData); + int updateParkingLotParkingSpaceInfoCountReduce(ParkingTurnoverData parkingTurnoverData); /** * 添加该停车场的 剩余车位信息 diff --git a/cjy-project/src/main/java/com/cjy/parking/service/impl/ParkingTurnoverDataServiceImpl.java b/cjy-project/src/main/java/com/cjy/parking/service/impl/ParkingTurnoverDataServiceImpl.java index b15377dc..486c9ee7 100644 --- a/cjy-project/src/main/java/com/cjy/parking/service/impl/ParkingTurnoverDataServiceImpl.java +++ b/cjy-project/src/main/java/com/cjy/parking/service/impl/ParkingTurnoverDataServiceImpl.java @@ -185,12 +185,22 @@ public class ParkingTurnoverDataServiceImpl implements IParkingTurnoverDataServi parkingTurnoverData.setCreateTime(DateUtils.getNowDate()); //判断是否有数据 如果有install 如果没有install if (parkingTurnoverDataMapper.getParkingLotParkingSpaceInfoCount(parkingTurnoverData) > 0) { - parkingTurnoverDataMapper.updateParkingLotParkingSpaceInfoCount(parkingTurnoverData); - + //如果是入场 + if(parkingTurnoverData.getCutsceneType().equals("1")){ +// 占用车位+1 + parkingTurnoverDataMapper.updateParkingLotParkingSpaceInfoCount(parkingTurnoverData); + }else { +// 占用车位-1 + parkingTurnoverDataMapper.updateParkingLotParkingSpaceInfoCountReduce(parkingTurnoverData); + } } else { - parkingTurnoverDataMapper.installPkingLotParkingSpaceInfoCount(parkingTurnoverData); - } + //如果是入场 + if(parkingTurnoverData.getCutsceneType().equals("1")){ + parkingTurnoverData.setOccupyParkingSpace(1); + parkingTurnoverDataMapper.installPkingLotParkingSpaceInfoCount(parkingTurnoverData); + } + } if (parkingTurnoverData.getCutsceneType().equals("2")) { //通过 车牌号获取 入场信息 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); @@ -226,10 +236,21 @@ public class ParkingTurnoverDataServiceImpl implements IParkingTurnoverDataServi parkingTurnoverData.setUpdateTime(DateUtils.getNowDate()); if (parkingTurnoverDataMapper.getParkingLotParkingSpaceInfoCount(parkingTurnoverData) > 0) { - parkingTurnoverDataMapper.updateParkingLotParkingSpaceInfoCount(parkingTurnoverData); - + //如果是入场 + if(parkingTurnoverData.getCutsceneType().equals("1")){ +// 占用车位+1 + parkingTurnoverDataMapper.updateParkingLotParkingSpaceInfoCount(parkingTurnoverData); + }else { +// 占用车位-1 + parkingTurnoverDataMapper.updateParkingLotParkingSpaceInfoCountReduce(parkingTurnoverData); + } } else { + //如果是入场 + if(parkingTurnoverData.getCutsceneType().equals("1")){ + parkingTurnoverData.setOccupyParkingSpace(1); parkingTurnoverDataMapper.installPkingLotParkingSpaceInfoCount(parkingTurnoverData); + } + } if (parkingTurnoverData.getCutsceneType().equals("2")) { //通过 车牌号获取 入场信息 diff --git a/cjy-project/src/main/java/com/cjy/parkinglotdataanalysis/service/impl/ParkingLotDataAnalysisServiceImpl.java b/cjy-project/src/main/java/com/cjy/parkinglotdataanalysis/service/impl/ParkingLotDataAnalysisServiceImpl.java index 10250690..8125e538 100644 --- a/cjy-project/src/main/java/com/cjy/parkinglotdataanalysis/service/impl/ParkingLotDataAnalysisServiceImpl.java +++ b/cjy-project/src/main/java/com/cjy/parkinglotdataanalysis/service/impl/ParkingLotDataAnalysisServiceImpl.java @@ -44,7 +44,7 @@ public class ParkingLotDataAnalysisServiceImpl implements ParkingLotDataAnalysis VehicleStatisticsVO vehicleStatisticsVO = new VehicleStatisticsVO(); vehicleStatisticsVO.setPlaceNum(vehicleStatisticsDTO.getPlaceNum()); vehicleStatisticsVO.setWarningNum(vehicleStatisticsDTO.getWarningNum()); - vehicleStatisticsVO.setRemainingParkingSpace(vehicleStatisticsDTO.getRemainingParkingSpace()); + vehicleStatisticsVO.setRemainingParkingSpace(vehicleStatisticsDTO.getPlaceNum()-vehicleStatisticsDTO.getOccupyParkingSpace()); Float saturation; if (vehicleStatisticsDTO.getOccupyParkingSpace() == 0 || vehicleStatisticsDTO.getPlaceNum().floatValue() == 0) { saturation = 0f; diff --git a/cjy-project/src/main/java/com/cjy/reservationdata/domain/AppointmentCenterData.java b/cjy-project/src/main/java/com/cjy/reservationdata/domain/AppointmentCenterData.java index a915c880..d4b900cc 100644 --- a/cjy-project/src/main/java/com/cjy/reservationdata/domain/AppointmentCenterData.java +++ b/cjy-project/src/main/java/com/cjy/reservationdata/domain/AppointmentCenterData.java @@ -85,6 +85,25 @@ public class AppointmentCenterData extends BaseEntity @Excel(name = "景区编码(必填)") private String externalId; + private int sourceType; + private String sourceDataId; + + public String getSourceDataId() { + return sourceDataId; + } + + public void setSourceDataId(String sourceDataId) { + this.sourceDataId = sourceDataId; + } + + public int getSourceType() { + return sourceType; + } + + public void setSourceType(int sourceType) { + this.sourceType = sourceType; + } + public Long getAppointmentPeopleId() { return appointmentPeopleId; diff --git a/cjy-project/src/main/resources/mapper/parking/ParkingTurnoverDataMapper.xml b/cjy-project/src/main/resources/mapper/parking/ParkingTurnoverDataMapper.xml index 7613c55a..3e1316ca 100644 --- a/cjy-project/src/main/resources/mapper/parking/ParkingTurnoverDataMapper.xml +++ b/cjy-project/src/main/resources/mapper/parking/ParkingTurnoverDataMapper.xml @@ -354,8 +354,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" UPDATE parking_lot_parking_space_info SET - remaining_parking_space = #{remainingParkingSpace}, - occupy_parking_space = #{occupyParkingSpace} + + occupy_parking_space =occupy_parking_space+1 + + WHERE parking_lot_id =#{parkingLotId} + + + UPDATE parking_lot_parking_space_info + SET + + occupy_parking_space =occupy_parking_space-1 WHERE parking_lot_id =#{parkingLotId} diff --git a/cjy-project/src/main/resources/mapper/parkinglotdataanalysis/ParkingLotDataAnalysisMapper.xml b/cjy-project/src/main/resources/mapper/parkinglotdataanalysis/ParkingLotDataAnalysisMapper.xml index d7f514b3..e16e39b2 100644 --- a/cjy-project/src/main/resources/mapper/parkinglotdataanalysis/ParkingLotDataAnalysisMapper.xml +++ b/cjy-project/src/main/resources/mapper/parkinglotdataanalysis/ParkingLotDataAnalysisMapper.xml @@ -17,11 +17,16 @@ select t1.id, t1.appointment_number, t1.appointment_date, t1.appointment_slot, t1.appointment_people_name, - t1.appointment_people_phone, t1.certificate_type, t1.documents_number, t1.verification_code, t1.state, t1.write_off_time, + t1.appointment_people_phone, t1.certificate_type, t1.documents_number, t1.verification_code, t1.state, t1.write_off_time,t1.source_type as sourceType, t1.data_sources, t1.del_flag, t1.create_by, t1.create_time, t1.update_by, t1.update_time, t1.organ_code,t2.resource_name as scenic_name from appointment_center_data t1 left join b_tour_info t2 on t1.external_id = t2.resource_code @@ -49,6 +49,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" and t1.write_off_time = #{writeOffTime} and t1.data_sources = #{dataSources} and t1.organ_code = #{organCode} + and t1.source_type = #{sourceType} and t1.del_flag != '2' order by t1.create_time desc @@ -116,12 +117,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" certificate_type, documents_number, verification_code, state, write_off_time, data_sources, - organ_code,appointment_people_id,external_id) + organ_code,appointment_people_id,external_id,source_data_id) VALUES (#{item.appointmentNumber}, #{item.scenicName}, #{item.appointmentDate}, #{item.appointmentSlot}, #{item.appointmentPeopleName}, #{item.appointmentPeoplePhone}, #{item.certificateType}, #{item.documentsNumber}, #{item.verificationCode}, #{item.state}, #{item.writeOffTime}, #{item.dataSources}, - #{item.organCode},#{item.appointmentPeopleId},#{item.externalId}) + #{item.organCode},#{item.appointmentPeopleId},#{item.externalId},#{sourceDataId}) diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java index a8a49485..b18e45a2 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java @@ -348,6 +348,8 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils { System.out.println(getPreviousYearUsingCalendar()); System.out.println(getHourBeforeCurrentTime()); + System.out.println(getDaysTimeToString(5)); + } public static String addSeconds(LocalDateTime dateTime, long seconds) { LocalDateTime futureDateTime = dateTime.plus(seconds, ChronoUnit.SECONDS); diff --git a/ruoyi-ui/src/views/reservationdata/appointmentrecord/index.vue b/ruoyi-ui/src/views/reservationdata/appointmentrecord/index.vue index c0febe52..e1b38a05 100644 --- a/ruoyi-ui/src/views/reservationdata/appointmentrecord/index.vue +++ b/ruoyi-ui/src/views/reservationdata/appointmentrecord/index.vue @@ -38,6 +38,8 @@ /> + + + + + + + {{ parseTime(scope.row.writeOffTime, '{y}-{m}-{d} {h}:{i}:{s}') }} + + +