package com.ruoyi.app.mendian; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.app.order.dto.OrderCreatItem; import com.ruoyi.app.order.dto.OrderCreateInput; import com.ruoyi.app.order.dto.OrderPushBodyDto; import com.ruoyi.app.service.UserService; import com.ruoyi.app.utils.DateUtil; import com.ruoyi.app.utils.ImageCompressUtils; import com.ruoyi.app.user.dto.StoreOutput; import com.ruoyi.app.utils.PayPush; import com.ruoyi.common.annotation.Anonymous; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.MessageUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.framework.manager.AsyncManager; import com.ruoyi.system.domain.*; import com.ruoyi.system.domain.vo.StoreOperatOutput; import com.ruoyi.system.mapper.PosStoreMapper; import com.ruoyi.system.mapper.SysConfigMapper; import com.ruoyi.system.service.*; import com.ruoyi.system.utils.Auth; import com.ruoyi.system.utils.AuthContext; import com.ruoyi.system.utils.JwtUtil; import io.swagger.models.auth.In; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import jakarta.servlet.http.HttpServletResponse; import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; /** * posstoreController * * @author ruoyi * @date 2023-05-14 */ @RestController @RequestMapping("/chanting/store") public class PosStoreController extends BaseController { @Autowired private IPosStoreService posStoreService; @Autowired private PosStoreMapper posStoreMapper; @Autowired private IPosCollectService posCollectService; @Autowired private IPosFenleiService posFenleiService; @Autowired private IInfoUserService infoUserService; @Autowired private IOperatingHoursService operatingHoursService; @Autowired private PosStoreEnrichService posStoreEnrichService; @Autowired private SysConfigMapper sysConfigMapper; @Autowired private IOrderParentService orderParentService; @Autowired private IPosOrderService posOrderService; @Autowired private IPosStoreEzpayService posStoreEzpayService; @Autowired private UserService userService; @Autowired private MerchantStoreAccessService merchantStoreAccessService; @Autowired private IMerchantSubaccountStoreService merchantSubaccountStoreService; /** * 根据评分查旬门店 * * @param longitude * @param latitude * @param page * @param juli * @param type * @return */ @Anonymous @GetMapping("/getPfStore") public AjaxResult getPfStore(@RequestParam BigDecimal longitude, @RequestParam BigDecimal latitude, @RequestParam Integer page, @RequestParam Integer juli, @RequestParam Integer type) { if (type == 0) { List list = posStoreMapper.getPingfStore(longitude, latitude, (page - 1) * 10, juli); return success(list); } else if (type == 1) { List list = posStoreMapper.getReduStore(longitude, latitude, (page - 1) * 10, juli); return success(list); } else { List list = posStoreMapper.getNewStore(longitude, latitude, (page - 1) * 10, juli); return success(list); } } //删除我的门店 @Anonymous @Auth @Transactional(rollbackFor = Exception.class) @GetMapping("/delemendian") public AjaxResult delemendian(@RequestHeader String token, @RequestParam String id) { Long userId = AuthContext.requireUserId(); merchantStoreAccessService.requireOwner(userId); merchantStoreAccessService.requireStoreAccess(userId, Long.valueOf(id)); QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("mendid", id); List list = posFenleiService.list(queryWrapper); if (list.size() > 0) { return error(MessageUtils.message("no.mendian.exist.classify.not.del")); } else { int rows = posStoreService.deletePosStoreById(Long.valueOf(id)); if (rows > 0) { merchantSubaccountStoreService.deleteByStoreId(Long.valueOf(id)); } return toAjax(rows); } } /** * H5端门店列表 */ @Anonymous @Auth @GetMapping("/storelistlist") public AjaxResult storelistlist(@RequestHeader String token, @RequestParam Integer page, @RequestParam Integer size) { Long id = AuthContext.requireUserId(); IPage stlist = new Page<>(page, size); QueryWrapper queryWrapper = new QueryWrapper<>(); // 判断是否为摊位主(type=4),摊位主通过 storeId 关联摊位 InfoUser loginUser = infoUserService.selectInfoUserByUserId(Long.valueOf(id)); if ("4".equals(loginUser.getUserType())) { if (loginUser.getStoreId() != null) { queryWrapper.eq("id", loginUser.getStoreId()); } else { queryWrapper.eq("id", -1); // 无关联摊位,返回空列表 } } else { Set storeIds = merchantStoreAccessService.getAccessibleStoreIds(id); if (storeIds.isEmpty()) { queryWrapper.eq("id", -1); } else { queryWrapper.in("id", storeIds); } } IPage list = posStoreService.page(stlist, queryWrapper); if (!list.getRecords().isEmpty()) { QueryWrapper wrapper = new QueryWrapper<>(); wrapper.in("md_id", list.getRecords().stream().map(PosStore::getId).collect(Collectors.toList())); List hourslist = operatingHoursService.list(wrapper); list.getRecords().forEach(posStore -> { posStore.setBusinessHours(getStoreOperatOutput(hourslist, Long.valueOf(posStore.getId()))); // 回显统一编号(统编),供商家端编辑门店时显示 posStore.setUbn(posStoreEzpayService.getUbn(Long.valueOf(posStore.getId()))); }); } return success(list); } //查询我的门店列表 @Anonymous @Auth @GetMapping("/getmystorelist") public AjaxResult getmystorelist(@RequestHeader String token) { Long id = AuthContext.requireUserId(); QueryWrapper queryWrapper = new QueryWrapper<>(); InfoUser loginUser = infoUserService.selectInfoUserByUserId(id); if (loginUser != null && "4".equals(loginUser.getUserType())) { queryWrapper.eq("id", loginUser.getStoreId() == null ? -1 : loginUser.getStoreId()); } else { Set storeIds = merchantStoreAccessService.getAccessibleStoreIds(id); if (storeIds.isEmpty()) { queryWrapper.eq("id", -1); } else { queryWrapper.in("id", storeIds); } } List list = posStoreService.list(queryWrapper); return success(list); } //查询门店列表 @Anonymous @GetMapping("/getstore") public AjaxResult getstore(@RequestHeader(defaultValue = "") String token, @RequestParam Integer id) { List list = new ArrayList<>(); if (!"".equals(token)) { JwtUtil jwtUtil = new JwtUtil(); String usid = jwtUtil.getusid(token); QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("user_id", usid); queryWrapper.eq("md_id", id); list = posCollectService.list(queryWrapper); } PosStore posStore = posStoreService.getById(id); // 回显统一编号(统编),实存于 pos_store_ezpay.ubn posStore.setUbn(posStoreEzpayService.getUbn(id.longValue())); List stores=new ArrayList<>(); stores.add(posStore); posStoreEnrichService.enrichStoreList(stores); StoreOutput storeOutput = new StoreOutput(); BeanUtils.copyProperties(stores.getFirst(), storeOutput); storeOutput.setCollect(!list.isEmpty() ? 1 : 0); return success(storeOutput); } /** * 商家收款账户(線下轉賬收银台展示用):门店 到 所属商家主账号 到 审核资料银行三字段 * 商家级数据,连锁门店共享同一收款账户;任一字段为空返回 data=null,客户端据此隐藏線下支付选项 */ @Anonymous @GetMapping("/bankInfo") public AjaxResult bankInfo(@RequestParam Integer id) { PosStore store = posStoreService.getById(id); if (store == null || store.getUserId() == null) { return success(null); } InfoUser merchant = infoUserService.selectInfoUserByUserId(store.getUserId()); if (merchant == null || StringUtils.isBlank(merchant.getBankAccountName()) || StringUtils.isBlank(merchant.getBankName()) || StringUtils.isBlank(merchant.getBankAccountNo())) { return success(null); } JSONObject data = new JSONObject(); data.put("accountName", merchant.getBankAccountName().trim()); data.put("bankName", merchant.getBankName().trim()); data.put("accountNo", merchant.getBankAccountNo().trim()); return success(data); } //根据行业分类查询门店列表 @Anonymous @GetMapping("/getstorelist") public AjaxResult getstorelist(@RequestParam BigDecimal longitude, @RequestParam BigDecimal latitude, @RequestParam Integer page, @RequestParam String area, @RequestParam Integer juli, @RequestParam(defaultValue = "") Integer sort, @RequestParam(defaultValue = "zh-TW", required = false) String language) { List list; if (sort == null) { list = posStoreMapper.getmdlist(longitude, latitude, (page - 1) * 20, "%" + area + "%", juli); } else { list = posStoreMapper.getdaidiq(longitude, latitude, (page - 1) * 20, "%" + area + "%", juli, sort); } posStoreEnrichService.enrichStoreList(list); // total 必须是符合条件总数,不能用当前页行数充当,否则客户端按 total 判断会误判"已加载完"导致翻页失效 long total = sort == null ? posStoreMapper.getmdlistCount("%" + area + "%") : posStoreMapper.getdaidiqCount("%" + area + "%", sort); Page result = posStoreEnrichService.buildStoreOutputPage(list, language, page, total); return success(result); } //根据服务分类查询门店列表 @Anonymous @GetMapping("/getserverlist") public AjaxResult getserverlist(@RequestParam BigDecimal longitude, @RequestParam BigDecimal latitude, @RequestParam Integer page, @RequestParam String area, @RequestParam Integer juli, @RequestParam(defaultValue = "") String serverType) { if (!"".equals(serverType)) { List list = posStoreMapper.getserverlist(longitude, latitude, (page - 1) * 20, "%" + area + "%", juli, "%" + serverType + "%"); return success(list); } else { List list = posStoreMapper.getmdlist(longitude, latitude, (page - 1) * 20, "%" + area + "%", juli); return success(list); } } //添加门店 @Anonymous @Auth @PostMapping("/addmendian") @Transactional public AjaxResult addmendian(@RequestHeader String token, @RequestBody PosStore posStore) { Long loginUserId = AuthContext.requireUserId(); InfoUser loginUser = infoUserService.selectInfoUserByUserId(loginUserId); if (posStore.getId() == null) { merchantStoreAccessService.requireOwner(loginUserId); userService.checkUserStatus(loginUserId); posStore.setUserId(loginUserId); } else { requireStoreAccess(loginUserId, loginUser, posStore.getId().longValue()); PosStore existing = posStoreService.getById(posStore.getId()); if (existing == null) { throw new ServiceException(MessageUtils.message("merchant.store.access.denied")); } posStore.setUserId(existing.getUserId()); } try { // 1. 先保存门店信息 Boolean org = posStoreService.saveOrUpdate(posStore); if (!org) { return error(); } // 2. 查询保存后的门店信息(使用ID查询,避免锁等待) PosStore store; if (posStore.getId() != null) { store = posStoreService.getById(posStore.getId()); } else { // 如果是新增,通过名称和用户ID查询 QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pos_name", posStore.getPosName()); wrapper.eq("user_id", posStore.getUserId()); store = posStoreService.getOne(wrapper); } if (store == null) { return error("门店信息保存失败"); } // 3. 处理营业时间信息 handlerBusinessHours(posStore, store); // 4. 统一保存统一编号(统编)到 pos_store_ezpay(不再走独立 saveUbn 接口) if (posStore.getUbn() != null) { posStoreEzpayService.uploadUbn(store.getId().longValue(), posStore.getUbn()); } return success(MessageUtils.message("no.success"), store); } catch (ServiceException exception) { throw exception; } catch (Exception exception) { logger.error("保存商家门店失败,userId:{},storeId:{}", loginUserId, posStore.getId(), exception); return error(MessageUtils.message("no.system.error")); } } // 统一编号(统编)已并入 addmendian 保存、storelistlist 回显(存于 pos_store_ezpay),不再有独立 saveUbn/getUbn 接口 /** * 更新门店信息处理营业时间 * @param input * @param store */ private void handlerBusinessHours(PosStore input, PosStore store) { if (input.getBusinessHours() != null && !input.getBusinessHours().isEmpty()) { // 先删除旧的营业时间记录 LambdaQueryWrapper query = new LambdaQueryWrapper<>(); query.eq(OperatingHours::getMdId, store.getId()); operatingHoursService.remove(query); // 批量插入新的营业时间记录 List operatingHours = new ArrayList<>(); input.getBusinessHours().forEach(o -> { o.getTimeSlots().forEach(time -> { OperatingHours op = new OperatingHours(); op.setStartTime(time.getStartTime()); op.setEndTime(time.getEndTime()); op.setDayOfWeek(time.getDayOfWeek()); op.setIsOpen(o.getIsOpen()); op.setMdId(Long.valueOf(store.getId())); operatingHours.add(op); }); }); if (!operatingHours.isEmpty()) { operatingHoursService.saveBatch(operatingHours); } } } /** * (商家端app使用)获取门店营业时间 * @param mdId 门店id * @return */ @Anonymous @Auth @GetMapping("/getMdBusinessHours") public AjaxResult getMdBusinessHours(@RequestHeader String token, @RequestParam Long mdId){ Long userId = AuthContext.requireUserId(); requireStoreAccess(userId, infoUserService.selectInfoUserByUserId(userId), mdId); LambdaQueryWrapper query=new LambdaQueryWrapper<>(); query.eq(OperatingHours::getMdId,mdId); List list = operatingHoursService.list(query); List data = new ArrayList<>(); if(!list.isEmpty()){ data = getStoreOperatOutput(list,mdId); } return success(data); } /** * 商家端app更新门店营业时间 * @param businessHours * @return */ @Anonymous @Auth @PostMapping("/saveMdBusinessHours") public AjaxResult saveMdBusinessHours(@RequestHeader String token, @RequestBody List businessHours) { if(businessHours == null || businessHours.isEmpty()) { throw new ServiceException(MessageUtils.message("no.mendian.not.set.business.hours")); } Long mdId = businessHours.get(0).getMdId(); Long userId = AuthContext.requireUserId(); requireStoreAccess(userId, infoUserService.selectInfoUserByUserId(userId), mdId); if (businessHours.stream().anyMatch(item -> !Objects.equals(mdId, item.getMdId()))) { throw new ServiceException(MessageUtils.message("merchant.store.access.denied")); } PosStore store = posStoreService.getById(businessHours.get(0).getMdId()); // 先删除旧的营业时间记录 LambdaQueryWrapper query = new LambdaQueryWrapper<>(); query.eq(OperatingHours::getMdId, store.getId()); operatingHoursService.remove(query); // 批量插入新的营业时间记录 List operatingHours = new ArrayList<>(); businessHours.forEach(o -> { o.getTimeSlots().forEach(time -> { OperatingHours op = new OperatingHours(); op.setStartTime(time.getStartTime()); op.setEndTime(time.getEndTime()); op.setDayOfWeek(time.getDayOfWeek()); op.setIsOpen(o.getIsOpen()); op.setMdId(Long.valueOf(store.getId())); operatingHours.add(op); }); }); if(!operatingHours.isEmpty()) { operatingHoursService.saveBatch(operatingHours); } return success(); } private void requireStoreAccess(Long loginUserId, InfoUser loginUser, Long storeId) { if (loginUser != null && "4".equals(loginUser.getUserType())) { if (!Objects.equals(loginUser.getStoreId(), storeId)) { throw new ServiceException(MessageUtils.message("merchant.store.access.denied")); } return; } merchantStoreAccessService.requireStoreAccess(loginUserId, storeId); } //返回营业时间(按星期分组) private List getStoreOperatOutput(List list, Long mdId){ List data= new ArrayList<>(); list=list.stream().filter(x-> x.getMdId().equals(mdId)).collect(Collectors.toList()); if(!list.isEmpty()){ Map> map = list.stream().collect(Collectors.groupingBy(OperatingHours::getDayOfWeek)); map.forEach((k,v)->{ data.add(new StoreOperatOutput(){ { setMdId(mdId); setDayOfWeek(k); setIsOpen(v.get(0).getIsOpen()); setTimeSlots(v); } }); }); } return data; } /** * 查询posstore列表 */ @PreAuthorize("@ss.hasPermi('chanting:store:list')") // @Anonymous @GetMapping("/list") public TableDataInfo list(PosStore posStore) { startPage(); List list = posStoreService.selectPosStoreList(posStore); for (PosStore store : list) { InfoUser user = infoUserService.getById(store.getUserId()); store.setUserName(user.getUserName()); } return getDataTable(list); } /** * 导出posstore列表 */ @PreAuthorize("@ss.hasPermi('chanting:store:export')") @Log(title = "posstore", businessType = BusinessType.EXPORT) @PostMapping("/export") public void export(HttpServletResponse response, PosStore posStore) { List list = posStoreService.selectPosStoreList(posStore); ExcelUtil util = new ExcelUtil(PosStore.class); util.exportExcel(response, list, MessageUtils.message("no.export.excel.posstore")); } /** * 获取posstore详细信息 */ @PreAuthorize("@ss.hasPermi('chanting:store:query')") @GetMapping(value = "/{id:\\d+}") public AjaxResult getInfo(@PathVariable("id") Long id) { PosStore posStore = posStoreService.selectPosStoreById(id); // 回显营业时间(按周几分组的 timeSlots)与统一编号(统编),供门店审核页显示 if (posStore != null) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(OperatingHours::getMdId, id); posStore.setBusinessHours(getStoreOperatOutput(operatingHoursService.list(wrapper), id)); // 统编实存于 pos_store_ezpay.ubn posStore.setUbn(posStoreEzpayService.getUbn(id)); } return success(posStore); } /** * 新增posstore */ @PreAuthorize("@ss.hasPermi('chanting:store:add')") @Log(title = "posstore", businessType = BusinessType.INSERT) @PostMapping public AjaxResult add(@RequestBody PosStore posStore) { return toAjax(posStoreService.insertPosStore(posStore)); } /** * 修改posstore */ @PreAuthorize("@ss.hasPermi('chanting:store:edit')") @Log(title = "posstore", businessType = BusinessType.UPDATE) @PutMapping public AjaxResult edit(@RequestBody PosStore posStore) { return toAjax(posStoreService.updatePosStore(posStore)); } /** * 修改posstore下架状态 */ @Anonymous @PutMapping("/changeOffShelf") public AjaxResult changeOffShelf(@RequestBody PosStore posStore) { Boolean res = posStoreService.saveOrUpdate(posStore); if (res) { return success(); } else { return error(); } } /** * 删除posstore */ @PreAuthorize("@ss.hasPermi('chanting:store:remove')") @Log(title = "posstore", businessType = BusinessType.DELETE) @DeleteMapping("/{ids}") public AjaxResult remove(@PathVariable Long[] ids) { return toAjax(posStoreService.deletePosStoreByIds(ids)); } /** * 压缩图片店铺的商品图片 */ @Anonymous @GetMapping("/compressStoreImage") public AjaxResult compressStoreImage(@RequestParam String idsStr) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); List ids = new ArrayList<>(); if (!StringUtils.isEmpty(idsStr)) { ids = Arrays.stream(idsStr.split(",")) .map(Integer::valueOf) .collect(Collectors.toList()); } queryWrapper.in(!ids.isEmpty(), PosStore::getId, ids); List list = posStoreService.list(queryWrapper); AtomicInteger count = new AtomicInteger(); list.forEach(food -> { String compressImage = ImageCompressUtils.compressImageByWebPath(food.getImage()); if (!compressImage.equals(food.getImage())) { food.setImage(compressImage); PosStore posStore = new PosStore(); posStore.setId(food.getId()); posStore.setImage(compressImage); posStoreService.saveOrUpdate(posStore); count.getAndIncrement(); System.out.println("store成功压缩的图片数量:" + count.get()); logger.info("store成功压缩的图片数量:" + count.get()); } }); return success("成功压缩的图片数量:" + count.get()); } }