From b2fce0dc7dc4ea5dec9792a2bc3ceb9d33d6e07b Mon Sep 17 00:00:00 2001 From: lidongdong <1459917685@qq.com> Date: 星期一, 04 九月 2023 13:59:52 +0800 Subject: [PATCH] 修改后台社区动态加载不出来 --- springcloud_k8s_panzhihuazhihuishequ/service_community/src/main/java/com/panzhihua/service_community/service/impl/ConvenientMerchantServiceImpl.java | 259 +++++++++++++++++++++++++++++++++++++++++---------- 1 files changed, 206 insertions(+), 53 deletions(-) diff --git a/springcloud_k8s_panzhihuazhihuishequ/service_community/src/main/java/com/panzhihua/service_community/service/impl/ConvenientMerchantServiceImpl.java b/springcloud_k8s_panzhihuazhihuishequ/service_community/src/main/java/com/panzhihua/service_community/service/impl/ConvenientMerchantServiceImpl.java index a5e3fa5..c973642 100644 --- a/springcloud_k8s_panzhihuazhihuishequ/service_community/src/main/java/com/panzhihua/service_community/service/impl/ConvenientMerchantServiceImpl.java +++ b/springcloud_k8s_panzhihuazhihuishequ/service_community/src/main/java/com/panzhihua/service_community/service/impl/ConvenientMerchantServiceImpl.java @@ -1,20 +1,7 @@ package com.panzhihua.service_community.service.impl; -import static java.util.Objects.isNull; -import static java.util.Objects.nonNull; -import static org.apache.commons.lang3.StringUtils.isNotBlank; - -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import javax.annotation.Resource; - -import org.springframework.beans.BeanUtils; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.NumberUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; @@ -22,35 +9,32 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.panzhihua.common.exceptions.ServiceException; -import com.panzhihua.common.model.dtos.community.convenient.ConvenientMerchantDTO; -import com.panzhihua.common.model.dtos.community.convenient.DisableOrEnableConvenientMerchantDTO; -import com.panzhihua.common.model.dtos.community.convenient.ExportMerchantDTO; -import com.panzhihua.common.model.dtos.community.convenient.PageClassifyMerchantDTO; -import com.panzhihua.common.model.dtos.community.convenient.PageConvenientMerchantDTO; -import com.panzhihua.common.model.dtos.community.convenient.PagePopularMerchantDTO; -import com.panzhihua.common.model.dtos.community.convenient.PageSearchDTO; -import com.panzhihua.common.model.dtos.community.convenient.ResetPasswordConvenientMerchantDTO; +import com.panzhihua.common.model.dtos.community.convenient.*; import com.panzhihua.common.model.dtos.grid.EventGridMemberPassResetDTO; import com.panzhihua.common.model.vos.LoginUserInfoVO; import com.panzhihua.common.model.vos.R; -import com.panzhihua.common.model.vos.community.convenient.ConvenientConsultationStatisticsVO; -import com.panzhihua.common.model.vos.community.convenient.ConvenientMerchantVO; -import com.panzhihua.common.model.vos.community.convenient.ConvenientProductSpecificationVO; -import com.panzhihua.common.model.vos.community.convenient.ConvenientProductVO; -import com.panzhihua.common.model.vos.community.convenient.ConvenientViewStatisticsVO; +import com.panzhihua.common.model.vos.community.convenient.*; import com.panzhihua.common.service.user.UserService; -import com.panzhihua.service_community.dao.ComActDAO; -import com.panzhihua.service_community.dao.ConvenientConsultationStatisticsDAO; -import com.panzhihua.service_community.dao.ConvenientMerchantDAO; -import com.panzhihua.service_community.dao.ConvenientProductDAO; -import com.panzhihua.service_community.dao.ConvenientServiceCategoryDAO; -import com.panzhihua.service_community.dao.ConvenientViewStatisticsDAO; -import com.panzhihua.service_community.model.dos.ComActDO; -import com.panzhihua.service_community.model.dos.ConvenientConsultationStatisticsDO; -import com.panzhihua.service_community.model.dos.ConvenientMerchantDO; -import com.panzhihua.service_community.model.dos.ConvenientServiceCategoryDO; -import com.panzhihua.service_community.model.dos.ConvenientViewStatisticsDO; +import com.panzhihua.common.utlis.Snowflake; +import com.panzhihua.service_community.dao.*; +import com.panzhihua.service_community.model.dos.*; import com.panzhihua.service_community.service.ConvenientMerchantService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +import static java.util.Objects.isNull; +import static java.util.Objects.nonNull; +import static org.apache.commons.lang3.StringUtils.isNotBlank; /** * @title: ConvenientMerchantServiceImpl @@ -60,6 +44,7 @@ * @date: 2021/09/16 16:14 */ @Service +@Slf4j public class ConvenientMerchantServiceImpl extends ServiceImpl<ConvenientMerchantDAO, ConvenientMerchantDO> implements ConvenientMerchantService { @Resource @@ -74,15 +59,36 @@ private ConvenientConsultationStatisticsDAO convenientConsultationStatisticsDAO; @Resource private ConvenientViewStatisticsDAO convenientViewStatisticsDAO; + @Resource + private ComShopFlowerEvaluateDAO comShopFlowerEvaluateDAO; + + private static final String DQ = "510402"; + private static final String RHQ = "510411"; @Override @Transactional(rollbackFor = Exception.class) public R addMerchant(ConvenientMerchantDTO convenientMerchantDTO) { - ComActDO comActDO = comActDAO.selectById(convenientMerchantDTO.getCommunityId()); + //校验微信手机号是否已使用 + String mobilePhone = convenientMerchantDTO.getMobilePhone(); + Integer count = this.baseMapper.selectCount(new LambdaQueryWrapper<ConvenientMerchantDO>().eq(ConvenientMerchantDO::getMobilePhone, mobilePhone)); + if (count > 0) { + R.fail("该微信手机号:" + mobilePhone + "已被使用!请更换"); + } ConvenientMerchantDO convenientMerchantDO = new ConvenientMerchantDO(); BeanUtils.copyProperties(convenientMerchantDTO, convenientMerchantDO); + if (convenientMerchantDTO.getCommunityId() == 0) { + if (DQ.equals(convenientMerchantDTO.getAreaCode())) { + convenientMerchantDO.setCommunityName("东区社区"); + } else if (RHQ.equals(convenientMerchantDTO.getAreaCode())) { + convenientMerchantDO.setCommunityName("仁和区社区"); + } else { + convenientMerchantDO.setCommunityName("西区社区"); + } + } else { + ComActDO comActDO = comActDAO.selectById(convenientMerchantDTO.getCommunityId()); + convenientMerchantDO.setCommunityName(comActDO.getName()); + } convenientMerchantDO.setUserId(0L); - convenientMerchantDO.setCommunityName(comActDO.getName()); convenientMerchantDO.setCreatedAt(new Date()); int insertResult = this.baseMapper.insert(convenientMerchantDO); if (insertResult > 0) { @@ -92,7 +98,7 @@ List<Long> serviceIds = convenientMerchantDTO.getServiceIds(); serviceIds.forEach(serviceId -> { ConvenientServiceCategoryDO convenientServiceCategoryDO = convenientServiceCategoryDAO.selectById(serviceId); - convenientServiceCategoryDAO.createMerchantServiceRelation(merchantId, serviceId, + convenientServiceCategoryDAO.createMerchantServiceRelation(Snowflake.getId(), merchantId, serviceId, convenientServiceCategoryDO.getName(), convenientMerchantDTO.getCreatedBy()); }); } @@ -100,7 +106,7 @@ //添加user R addUserResult = userService.addConvenientMerchantUser(convenientMerchantDTO); if (R.isOk(addUserResult)) { - Long merchantUserId = ((Integer) addUserResult.getData()).longValue(); + Long merchantUserId = Long.parseLong(addUserResult.getData().toString()); convenientMerchantDO.setUserId(merchantUserId); this.baseMapper.updateById(convenientMerchantDO); } else { @@ -113,14 +119,25 @@ @Transactional(rollbackFor = Exception.class) public R putMerchant(ConvenientMerchantDTO convenientMerchantDTO) { Long merchantId = convenientMerchantDTO.getId(); + String mobilePhone = convenientMerchantDTO.getMobilePhone(); + ConvenientMerchantDO merchantDO = this.baseMapper.selectOne(new LambdaQueryWrapper<ConvenientMerchantDO>().eq(ConvenientMerchantDO::getMobilePhone, mobilePhone)); ConvenientMerchantDO convenientMerchantDO = this.baseMapper.selectById(merchantId); if (isNull(convenientMerchantDO)) { return R.fail("商家不存在"); } + Long createBy = convenientMerchantDO.getCreatedBy(); + BeanUtils.copyProperties(convenientMerchantDTO, convenientMerchantDO); + if (nonNull(merchantDO) && !merchantDO.getId().equals(convenientMerchantDO.getId())) { + R.fail("该微信手机号:" + mobilePhone + "已被使用!请更换"); + } Long communityId = convenientMerchantDTO.getCommunityId(); if (nonNull(communityId)) { ComActDO comActDO = comActDAO.selectById(communityId); - convenientMerchantDO.setCommunityName(comActDO.getName()); + if (comActDO != null) { + convenientMerchantDO.setCommunityName(comActDO.getName()); + } else { + convenientMerchantDO.setCommunityName("西区社区"); + } } String account = convenientMerchantDTO.getAccount(); if (isNotBlank(account)) { @@ -135,11 +152,12 @@ convenientServiceCategoryDAO.deleteMerchantServiceRelation(merchantId); serviceIds.forEach(serviceId -> { ConvenientServiceCategoryDO convenientServiceCategoryDO = convenientServiceCategoryDAO.selectById(serviceId); - convenientServiceCategoryDAO.createMerchantServiceRelation(merchantId, serviceId, - convenientServiceCategoryDO.getName(), convenientMerchantDTO.getCreatedBy()); + convenientServiceCategoryDAO.createMerchantServiceRelation(Snowflake.getId(), merchantId, serviceId, + convenientServiceCategoryDO.getName(), createBy); }); } - BeanUtils.copyProperties(convenientMerchantDTO, convenientMerchantDO); + + convenientMerchantDO.setIntroduction(convenientMerchantDTO.getIntroduction()); this.baseMapper.updateById(convenientMerchantDO); return R.ok(); } @@ -159,20 +177,37 @@ page.setSize(pageConvenientMerchantDTO.getPageSize()); page.setCurrent(pageConvenientMerchantDTO.getPageNum()); IPage<ConvenientMerchantVO> iPage = this.baseMapper.pageMerchant(page, pageConvenientMerchantDTO); + if (nonNull(pageConvenientMerchantDTO.getServiceId())) { + List<ConvenientMerchantVO> records = iPage.getRecords(); + if (!records.isEmpty()) { + records.forEach(record -> { + String serviceScope = convenientServiceCategoryDAO.selectServiceScopeByMerchantId(record.getId()); + record.setServiceScope(serviceScope); + }); + } + } return R.ok(iPage); } @Override public R getMerchant(Long merchantId) { ConvenientMerchantVO convenientMerchantVO = this.baseMapper.selectMerchantById(merchantId); - List<Long> serviceIds = convenientServiceCategoryDAO.selectServiceIdsForMerchant(merchantId); + List<String> serviceIds = convenientServiceCategoryDAO.selectServiceIdsForMerchant(merchantId); convenientMerchantVO.setServiceIds(serviceIds); return R.ok(convenientMerchantVO); } @Override public R disableOrEnableMerchant(DisableOrEnableConvenientMerchantDTO disableOrEnableConvenientMerchantDTO) { + List<ConvenientMerchantDO> convenientMerchantDOList = this.baseMapper.selectList(new QueryWrapper<ConvenientMerchantDO>() + .lambda().in(ConvenientMerchantDO::getId, disableOrEnableConvenientMerchantDTO.getIds())); + List<Long> userIds = convenientMerchantDOList.stream().map(ConvenientMerchantDO::getUserId).collect(Collectors.toList()); + disableOrEnableConvenientMerchantDTO.setUserIds(userIds); R result = userService.disableOrEnableMerchantUsers(disableOrEnableConvenientMerchantDTO); + int type = disableOrEnableConvenientMerchantDTO.getType().intValue(); + if (type == 2) { + this.baseMapper.batchUpdateBusinessStatus(convenientMerchantDOList, 0); + } if (R.isOk(result)) { return R.ok(); } @@ -181,16 +216,19 @@ @Override public R resetPasswordMerchant(ResetPasswordConvenientMerchantDTO resetPasswordConvenientMerchantDTO) { + List<ConvenientMerchantDO> convenientMerchantDOList = this.baseMapper.selectList(new QueryWrapper<ConvenientMerchantDO>() + .lambda().in(ConvenientMerchantDO::getId, resetPasswordConvenientMerchantDTO.getIds())); + List<Long> userIds = convenientMerchantDOList.stream().map(ConvenientMerchantDO::getUserId).collect(Collectors.toList()); EventGridMemberPassResetDTO eventGridMemberPassResetDTO = new EventGridMemberPassResetDTO(); eventGridMemberPassResetDTO.setPassword(resetPasswordConvenientMerchantDTO.getPassword()); - eventGridMemberPassResetDTO.setIds(resetPasswordConvenientMerchantDTO.getIds()); + eventGridMemberPassResetDTO.setIds(userIds); return userService.gridMemberPassReset(eventGridMemberPassResetDTO); } @Override public R<ConvenientMerchantVO> getUserMerchantInfoByAccount(String account) { try { - R<LoginUserInfoVO> loginUserInfoVOR = userService.getUserInfo(account + "_10"); + R<LoginUserInfoVO> loginUserInfoVOR = userService.getUserInfo(account + "_5"); LoginUserInfoVO loginUserInfoVO = JSONObject.parseObject(JSONObject.toJSONString(loginUserInfoVOR.getData()), LoginUserInfoVO.class); @@ -213,6 +251,20 @@ } @Override + public R<ConvenientMerchantVO> getMerchantInfoByAccount(String account) { + try { + List<ConvenientMerchantVO> merchantDetailByAccount = this.baseMapper.getMerchantDetailByAccount(account); + if (CollUtil.isEmpty(merchantDetailByAccount)) { + return R.fail(500, "该账号不存在"); + } + ConvenientMerchantVO convenientMerchantVO = merchantDetailByAccount.get(0); + return R.ok(convenientMerchantVO); + } catch (Exception e) { + return R.fail(); + } + } + + @Override public R<ConvenientMerchantVO> getUserConvenientMerchantInfo(Long userId) { ConvenientMerchantDO merchantDO = this.baseMapper.selectOne(new QueryWrapper<ConvenientMerchantDO>() .lambda().eq(ConvenientMerchantDO::getUserId, userId)); @@ -222,17 +274,21 @@ Long merchantId = merchantDO.getId(); ConvenientMerchantVO convenientMerchantVO = new ConvenientMerchantVO(); BeanUtils.copyProperties(merchantDO, convenientMerchantVO); - List<Long> serviceIds = convenientServiceCategoryDAO.selectServiceIdsForMerchant(merchantId); + List<String> serviceIds = convenientServiceCategoryDAO.selectServiceIdsForMerchant(merchantId); convenientMerchantVO.setServiceIds(serviceIds); Date nowDate = new Date(); SimpleDateFormat mothFormat = new SimpleDateFormat("yyyy-MM"); SimpleDateFormat dayFormat = new SimpleDateFormat("yyyy-MM-dd"); String moth = mothFormat.format(nowDate); String day = dayFormat.format(nowDate); + int consultationCount = convenientConsultationStatisticsDAO.selectTotalConsultationVolume(merchantId); int monthConsultationVolume = convenientConsultationStatisticsDAO.selectMonthConsultationVolume(merchantId, moth); int dayConsultationVolume = convenientConsultationStatisticsDAO.selectDayConsultationVolume(merchantId, day); + Integer viewCount = convenientViewStatisticsDAO.selectTotalViewNum(merchantId); int monthViewNum = convenientViewStatisticsDAO.selectMonthViewNum(merchantId, moth); int dayViewNum = convenientViewStatisticsDAO.selectDayViewNum(merchantId, day); + convenientMerchantVO.setConsultationVolume(consultationCount); + convenientMerchantVO.setViewNum(viewCount); convenientMerchantVO.setMonthConsultationVolume(monthConsultationVolume); convenientMerchantVO.setDayConsultationVolume(dayConsultationVolume); convenientMerchantVO.setMonthViewNum(monthViewNum); @@ -248,7 +304,27 @@ Page page = new Page<>(); page.setSize(pagePopularMerchantDTO.getPageSize()); page.setCurrent(pagePopularMerchantDTO.getPageNum()); - IPage<ConvenientMerchantVO> merchantVOList = this.baseMapper.getPopularMerchants(page, pagePopularMerchantDTO.getCommunityId(), currentMon); + IPage<ConvenientMerchantVO> merchantVOList = this.baseMapper.getPopularMerchants(page, pagePopularMerchantDTO.getCommunityId(), currentMon, pagePopularMerchantDTO.getAreaCode()); + if (pagePopularMerchantDTO.getPageNum().equals(1L)) { + //金沙江默认第一个 + List<ConvenientMerchantVO> merchantVOS = new ArrayList<>(); + ConvenientMerchantVO merchantVO = new ConvenientMerchantVO(); + merchantVO.setName("金沙江智慧物流商贸城"); + merchantVO.setLogo("https://www.psciio.com//idcard/0694d975ed4d4c49bcfb728a678518f2.jpg"); + merchantVO.setIntroduction("农产直销、综合商贸、冷链储运、中央厨房、检验检疫、农博会展、总部商务、综合服务。"); + merchantVO.setServiceScope(""); + merchantVO.setConsultationVolume(0); + merchantVO.setMonthConsultationVolume(0); + merchantVOS.add(merchantVO); + //第一页默认把犇师傅维修中心加载到第一个 + List<ConvenientMerchantVO> merchantList = this.baseMapper.selectMerchantByName(pagePopularMerchantDTO.getCommunityId(), currentMon); + if (merchantList != null && merchantList.size() > 0) { + merchantVOS.addAll(merchantList); + merchantVOS.addAll(merchantVOList.getRecords()); + merchantVOList.setRecords(merchantVOS); + } + + } return R.ok(merchantVOList); } @@ -261,11 +337,19 @@ page.setSize(pageClassifyMerchantDTO.getPageSize()); page.setCurrent(pageClassifyMerchantDTO.getPageNum()); IPage<ConvenientMerchantVO> merchantVOList = this.baseMapper.getClassifyMerchants(page, pageClassifyMerchantDTO, currentMon); + List<ConvenientMerchantVO> records = merchantVOList.getRecords(); + if (!records.isEmpty()) { + records.forEach(record -> { + String serviceScope = convenientServiceCategoryDAO.selectServiceScopeByMerchantId(record.getId()); + record.setServiceScope(serviceScope); + }); + } return R.ok(merchantVOList); } /** * 小程序获取商家详情 + * * @param merchantId * @return */ @@ -313,6 +397,10 @@ @Override public R consultMerchant(Long merchantId) { + ConvenientMerchantDO merchantDO = this.baseMapper.selectById(merchantId); + if (isNull(merchantDO)) { + return R.fail("商家不存在"); + } SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); String nowDate = simpleDateFormat.format(new Date()); ConvenientConsultationStatisticsDO statisticsDO = convenientConsultationStatisticsDAO.selectOne(new LambdaQueryWrapper<ConvenientConsultationStatisticsDO>() @@ -327,6 +415,10 @@ @Override public R incrMerchantView(Long merchantId) { + ConvenientMerchantDO merchantDO = this.baseMapper.selectById(merchantId); + if (isNull(merchantDO)) { + return R.fail("商家不存在"); + } SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); String nowDate = simpleDateFormat.format(new Date()); ConvenientViewStatisticsDO statisticsDO = convenientViewStatisticsDAO.selectOne(new LambdaQueryWrapper<ConvenientViewStatisticsDO>() @@ -341,11 +433,24 @@ @Override public R exportMerchant(ExportMerchantDTO exportMerchantDTO) { - return R.ok(this.baseMapper.exportMerchant(exportMerchantDTO)); + List<Long> needExportIds = exportMerchantDTO.getIds(); + if (nonNull(needExportIds) && !needExportIds.isEmpty()) { + //根据id导出 + return R.ok(this.baseMapper.exportMerchantByIds(needExportIds)); + } + List<ExportMerchantVO> exportMerchantVOList = this.baseMapper.exportMerchantBySearch(exportMerchantDTO); + if (nonNull(exportMerchantDTO.getServiceId()) && !exportMerchantVOList.isEmpty()) { + exportMerchantVOList.forEach(merchant -> { + String serviceScope = convenientServiceCategoryDAO.selectServiceScopeByMerchantId(merchant.getId()); + merchant.setServiceScope(serviceScope); + }); + } + return R.ok(exportMerchantVOList); } /** * 定时任务每隔半小时将商家浏览量和咨询量总值计入指定商家数据中 + * * @return */ @Override @@ -356,4 +461,52 @@ this.baseMapper.batchUpdateMerchantViewNum(viewVOList); return R.ok(); } + + /** + * check商家/店铺是否有效 + * + * @param userId + * @return + */ + @Override + public Boolean checkStoreIsValid(Long userId) { + R<LoginUserInfoVO> loginUserInfo = userService.getUserInfoByUserId(userId.toString()); + LoginUserInfoVO loginUserInfoVO = + JSONObject.parseObject(JSONObject.toJSONString(loginUserInfo.getData()), LoginUserInfoVO.class); + if (isNull(loginUserInfoVO) || !loginUserInfoVO.getType().equals(10) || loginUserInfoVO.getStatus() != 1) { + return false; + } + return true; + } + + @Override + public R getMerchantByUserId(Long userId) { + ConvenientMerchantVO convenientMerchantVO = this.baseMapper.selectMerchantByUserId(userId); + if (isNull(convenientMerchantVO)) { + return R.fail("商家不存在"); + } + Long merchantId = convenientMerchantVO.getId(); + List<String> serviceIds = convenientServiceCategoryDAO.selectServiceIdsForMerchant(merchantId); + convenientMerchantVO.setServiceIds(serviceIds); + BigDecimal score = comShopFlowerEvaluateDAO.statisticsScore(merchantId); + convenientMerchantVO.setScore(null == score ? BigDecimal.ZERO : NumberUtil.round(score, 1)); + Date nowDate = new Date(); + SimpleDateFormat mothFormat = new SimpleDateFormat("yyyy-MM"); + SimpleDateFormat dayFormat = new SimpleDateFormat("yyyy-MM-dd"); + String moth = mothFormat.format(nowDate); + String day = dayFormat.format(nowDate); + int consultationCount = convenientConsultationStatisticsDAO.selectTotalConsultationVolume(merchantId); + int monthConsultationVolume = convenientConsultationStatisticsDAO.selectMonthConsultationVolume(merchantId, moth); + int dayConsultationVolume = convenientConsultationStatisticsDAO.selectDayConsultationVolume(merchantId, day); + Integer viewCount = convenientViewStatisticsDAO.selectTotalViewNum(merchantId); + int monthViewNum = convenientViewStatisticsDAO.selectMonthViewNum(merchantId, moth); + int dayViewNum = convenientViewStatisticsDAO.selectDayViewNum(merchantId, day); + convenientMerchantVO.setConsultationVolume(consultationCount); + convenientMerchantVO.setViewNum(viewCount); + convenientMerchantVO.setMonthConsultationVolume(monthConsultationVolume); + convenientMerchantVO.setDayConsultationVolume(dayConsultationVolume); + convenientMerchantVO.setMonthViewNum(monthViewNum); + convenientMerchantVO.setDayViewNum(dayViewNum); + return R.ok(convenientMerchantVO); + } } -- Gitblit v1.7.1