| | |
| | | import cn.hutool.core.date.DateUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.baomidou.mybatisplus.enums.SqlLike; |
| | | import com.baomidou.mybatisplus.mapper.EntityWrapper; |
| | | import com.baomidou.mybatisplus.mapper.Wrapper; |
| | | import com.baomidou.mybatisplus.plugins.Page; |
| | | import com.sinata.common.enums.EnumAuditState; |
| | | import com.sinata.common.enums.EnumIsDelete; |
| | | import com.sinata.common.enums.EnumIsSystemNotice; |
| | | import com.sinata.common.enums.EnumMemberGrade; |
| | | import com.sinata.common.enums.*; |
| | | import com.sinata.common.enums.mall.EnumMallGoodsGroupType; |
| | | import com.sinata.common.enums.mall.EnumMallOrderState; |
| | | import com.sinata.core.base.controller.BaseController; |
| | | import com.sinata.core.base.tips.ErrorTip; |
| | | import com.sinata.core.base.tips.SuccessTip; |
| | | import com.sinata.core.common.annotion.BussinessLog; |
| | | import com.sinata.core.common.annotion.Permission; |
| | | import com.sinata.core.common.constant.factory.PageFactory; |
| | | import com.sinata.core.shiro.ShiroKit; |
| | | import com.sinata.core.shiro.ShiroUser; |
| | | import com.sinata.core.util.Convert; |
| | | import com.sinata.core.util.ExcelExportUtil; |
| | | import com.sinata.core.util.SqlUtil; |
| | |
| | | import com.sinata.modular.member.model.MemUserRelation; |
| | | import com.sinata.modular.member.service.IMemUserRelationService; |
| | | import com.sinata.modular.member.service.IMemUserService; |
| | | import com.sinata.modular.system.model.Role; |
| | | import com.sinata.modular.system.model.SystemNotice; |
| | | import com.sinata.modular.system.model.TCityRegion; |
| | | import com.sinata.modular.system.service.IRoleService; |
| | | import com.sinata.modular.system.service.ISystemNoticeService; |
| | | import com.sinata.modular.system.service.ITCityRegionService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | |
| | | @Autowired |
| | | private ISystemNoticeService systemNoticeService; |
| | | |
| | | @Autowired |
| | | private IRoleService roleService; |
| | | |
| | | /** |
| | | * 跳转到会员用户信息首页 |
| | | */ |
| | | @RequestMapping("") |
| | | public String index(Model model) { |
| | | return PREFIX + "memUserSales.html"; |
| | | boolean admin = ShiroKit.isAdmin(); |
| | | if (admin) { |
| | | return PREFIX + "memUserSales.html"; |
| | | } else { |
| | | return PREFIX + "memUserSalesAuth.html"; |
| | | } |
| | | } |
| | | |
| | | @ResponseBody |
| | |
| | | } |
| | | if (!StringUtils.isEmpty(endTime)) { |
| | | wrapper.le("apply_time", endTime + " 23:59:59"); |
| | | } |
| | | |
| | | try { |
| | | // 【城市管理员】数据查询 |
| | | ShiroUser shiroUser = ShiroKit.getUser(); |
| | | List<Integer> roleList = shiroUser.getRoleList(); |
| | | List<Integer> cityRoleList = roleService.selectList( |
| | | new EntityWrapper<Role>().in("id", roleList)).stream().map(Role::getCityRole) |
| | | .collect( |
| | | Collectors.toList()); |
| | | if (cityRoleList.contains(EnumCityRole.CITY_ROLE.index)) { |
| | | // 市级城市管理员 |
| | | wrapper.like("o.city_code", shiroUser.getCityCode().substring(0, 4), SqlLike.RIGHT); |
| | | } |
| | | else if (cityRoleList.contains(EnumCityRole.PROVINCE_ROLE.index)) { |
| | | // 省级城市管理员 |
| | | wrapper.like("o.city_code", shiroUser.getCityCode().substring(0, 2), SqlLike.RIGHT); |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | // 查询数据列表 |
| | |
| | | if (parentV4V5User[0] != null) { |
| | | map.put("v4ShowId", parentV4V5User[0].getShowId()); |
| | | map.put("v4Team", parentV4V5User[0].getRealName()); |
| | | } else if (parentV4V5User[1] != null) { |
| | | map.put("v4ShowId", parentV4V5User[1].getShowId()); |
| | | map.put("v4Team", parentV4V5User[1].getRealName()); |
| | | map.put("v5ShowId", parentV4V5User[1].getShowId()); |
| | | map.put("v5Team", parentV4V5User[1].getRealName()); |
| | | } |
| | | if (parentV4V5User[1] != null) { |
| | | map.put("v5ShowId", parentV4V5User[1].getShowId()); |
| | |
| | | map.put("v4Team", map.get("real_name")); |
| | | } |
| | | if (userMemberGradeId == EnumMemberGrade.G_5.index) { |
| | | // 当是:市场总监后,城市合伙人无数据时,城市合伙人信息需显示本人的信息(只是做展示,不影响任何功能) |
| | | map.put("v4ShowId", map.get("show_id")); |
| | | map.put("v4Team", map.get("real_name")); |
| | | map.put("v5ShowId", map.get("show_id")); |
| | | map.put("v5Team", map.get("real_name")); |
| | | } |
| | |
| | | /** |
| | | * 导出用户列表 |
| | | */ |
| | | @Permission |
| | | @ResponseBody |
| | | @RequestMapping(value = "/export") |
| | | public void export(String beginTime, String endTime, String nickName, String phone, String showId, Integer isLock, Integer isLeaveOffice, Integer memberGradeId, HttpServletResponse response) { |
| | | boolean admin = ShiroKit.isAdmin(); |
| | | List<Map<String, Object>> list = this.wrapperList(null, beginTime, endTime, nickName, phone, showId, isLock, isLeaveOffice, memberGradeId); |
| | | |
| | | // 表格数据【封装】 |
| | | List<List<Object>> dataList = new ArrayList<>(); |
| | | |
| | | // 头部列【封装】 |
| | | List<Object> shellList = new ArrayList<>(); |
| | | shellList.add("工号"); |
| | | shellList.add("提交时间"); |
| | | shellList.add("推荐人"); |
| | | shellList.add("推荐人所在城市"); |
| | | shellList.add("姓名"); |
| | | shellList.add("性别"); |
| | | shellList.add("生日"); |
| | | shellList.add("联系电话"); |
| | | shellList.add("证件类型"); |
| | | shellList.add("证件号码"); |
| | | shellList.add("银行卡号"); |
| | | shellList.add("品行分"); |
| | | shellList.add("审核状态"); |
| | | shellList.add("职级"); |
| | | shellList.add("积分"); |
| | | shellList.add("入司时间"); |
| | | shellList.add("状态"); |
| | | shellList.add("城市合伙人工号"); |
| | | shellList.add("城市合伙人团队"); |
| | | shellList.add("市场总监工号"); |
| | | shellList.add("市场总监团队"); |
| | | dataList.add(shellList); |
| | | |
| | | // 详细数据列【封装】 |
| | | for (Map<String, Object> map : list) { |
| | | shellList = new ArrayList<>(); |
| | | shellList.add(map.get("show_id")); |
| | | shellList.add(map.get("apply_time")); |
| | | shellList.add(map.get("equityUserRealName")); |
| | | shellList.add(map.get("equityUserCityCode")); |
| | | shellList.add(map.get("real_name")); |
| | | shellList.add(map.get("sex")); |
| | | shellList.add(map.get("birthday")); |
| | | shellList.add(map.get("phone")); |
| | | shellList.add(Convert.toInt(map.get("card_type")) == 0 ? "身份证" : "护照"); |
| | | shellList.add(map.get("id_card")); |
| | | shellList.add(map.get("bank_number")); |
| | | shellList.add(map.get("credit_score")); |
| | | shellList.add(EnumAuditState.getMarkByIndex(Convert.toInt(map.get("audit_state")))); |
| | | shellList.add(EnumMemberGrade.getMarkByIndex(Convert.toInt(map.get("member_grade_id")))); |
| | | shellList.add(map.get("integral")); |
| | | shellList.add(map.get("audit_time")); |
| | | Integer isLeaveOfficeNum = Convert.toInt(map.get("is_leave_office")); |
| | | shellList.add(isLeaveOfficeNum == 0 ? "在职" : isLeaveOfficeNum == 1 ? "离职" : "-"); |
| | | shellList.add(map.get("v4ShowId")); |
| | | shellList.add(map.get("v4Team")); |
| | | shellList.add(map.get("v5ShowId")); |
| | | shellList.add(map.get("v5Team")); |
| | | if (admin) { |
| | | // 头部列【封装】 |
| | | List<Object> shellList = new ArrayList<>(); |
| | | shellList.add("工号"); |
| | | shellList.add("提交时间"); |
| | | shellList.add("推荐人工号"); |
| | | shellList.add("推荐人"); |
| | | shellList.add("推荐人所在城市"); |
| | | shellList.add("姓名"); |
| | | shellList.add("性别"); |
| | | shellList.add("生日"); |
| | | shellList.add("联系电话"); |
| | | shellList.add("证件类型"); |
| | | shellList.add("证件号码"); |
| | | shellList.add("银行卡号"); |
| | | shellList.add("品行分"); |
| | | shellList.add("审核状态"); |
| | | shellList.add("佣金等级"); |
| | | shellList.add("积分"); |
| | | shellList.add("入司时间"); |
| | | shellList.add("状态"); |
| | | shellList.add("城市合伙人工号"); |
| | | shellList.add("城市合伙人团队"); |
| | | shellList.add("市场总监工号"); |
| | | shellList.add("市场总监团队"); |
| | | dataList.add(shellList); |
| | | |
| | | // 详细数据列【封装】 |
| | | for (Map<String, Object> map : list) { |
| | | shellList = new ArrayList<>(); |
| | | shellList.add(map.get("show_id")); |
| | | shellList.add(map.get("apply_time")); |
| | | shellList.add(map.get("equityUserShowId")); |
| | | shellList.add(map.get("equityUserRealName")); |
| | | shellList.add(map.get("equityUserCityCode")); |
| | | shellList.add(map.get("real_name")); |
| | | shellList.add(map.get("sex")); |
| | | shellList.add(map.get("birthday")); |
| | | shellList.add(map.get("phone")); |
| | | shellList.add(Convert.toInt(map.get("card_type")) == 0 ? "身份证" : "护照"); |
| | | shellList.add(map.get("id_card")); |
| | | shellList.add(map.get("bank_number")); |
| | | shellList.add(map.get("credit_score")); |
| | | shellList.add(EnumAuditState.getMarkByIndex(Convert.toInt(map.get("audit_state")))); |
| | | shellList.add(EnumMemberGrade.getAliasByIndex(Convert.toInt(map.get("member_grade_id")))); |
| | | shellList.add(map.get("integral")); |
| | | shellList.add(map.get("audit_time")); |
| | | Integer isLeaveOfficeNum = Convert.toInt(map.get("is_leave_office")); |
| | | shellList.add(isLeaveOfficeNum == 0 ? "在职" : isLeaveOfficeNum == 1 ? "离职" : "-"); |
| | | shellList.add(map.get("v4ShowId")); |
| | | shellList.add(map.get("v4Team")); |
| | | shellList.add(map.get("v5ShowId")); |
| | | shellList.add(map.get("v5Team")); |
| | | dataList.add(shellList); |
| | | } |
| | | } else { |
| | | // 头部列【封装】 |
| | | List<Object> shellList = new ArrayList<>(); |
| | | shellList.add("工号"); |
| | | shellList.add("提交时间"); |
| | | shellList.add("推荐人工号"); |
| | | shellList.add("推荐人"); |
| | | shellList.add("推荐人所在城市"); |
| | | shellList.add("姓名"); |
| | | shellList.add("性别"); |
| | | shellList.add("生日"); |
| | | shellList.add("证件类型"); |
| | | shellList.add("品行分"); |
| | | shellList.add("审核状态"); |
| | | shellList.add("佣金等级"); |
| | | shellList.add("积分"); |
| | | shellList.add("入司时间"); |
| | | shellList.add("状态"); |
| | | shellList.add("城市合伙人工号"); |
| | | shellList.add("城市合伙人团队"); |
| | | shellList.add("市场总监工号"); |
| | | shellList.add("市场总监团队"); |
| | | dataList.add(shellList); |
| | | |
| | | // 详细数据列【封装】 |
| | | for (Map<String, Object> map : list) { |
| | | shellList = new ArrayList<>(); |
| | | shellList.add(map.get("show_id")); |
| | | shellList.add(map.get("apply_time")); |
| | | shellList.add(map.get("equityUserShowId")); |
| | | shellList.add(map.get("equityUserRealName")); |
| | | shellList.add(map.get("equityUserCityCode")); |
| | | shellList.add(map.get("real_name")); |
| | | shellList.add(map.get("sex")); |
| | | shellList.add(map.get("birthday")); |
| | | shellList.add(Convert.toInt(map.get("card_type")) == 0 ? "身份证" : "护照"); |
| | | shellList.add(map.get("credit_score")); |
| | | shellList.add(EnumAuditState.getMarkByIndex(Convert.toInt(map.get("audit_state")))); |
| | | shellList.add(EnumMemberGrade.getAliasByIndex(Convert.toInt(map.get("member_grade_id")))); |
| | | shellList.add(map.get("integral")); |
| | | shellList.add(map.get("audit_time")); |
| | | Integer isLeaveOfficeNum = Convert.toInt(map.get("is_leave_office")); |
| | | shellList.add(isLeaveOfficeNum == 0 ? "在职" : isLeaveOfficeNum == 1 ? "离职" : "-"); |
| | | shellList.add(map.get("v4ShowId")); |
| | | shellList.add(map.get("v4Team")); |
| | | shellList.add(map.get("v5ShowId")); |
| | | shellList.add(map.get("v5Team")); |
| | | dataList.add(shellList); |
| | | } |
| | | } |
| | | |
| | | try { |
| | | String title = "营销员"; |
| | | // 调用工具类进行导出 |
| | |
| | | return PREFIX + "memUserSales_audit.html"; |
| | | } |
| | | |
| | | @Permission |
| | | @BussinessLog(value = "营销人员管理-审核") |
| | | @ResponseBody |
| | | @RequestMapping(value = "/audit") |
| | |
| | | } |
| | | |
| | | String setSql = "audit_state = " + state |
| | | + ", audit_time = NOW()" |
| | | + ", remark = " + SqlUtil.addSingleQuotes(remark); |
| | | if (state == 1) { |
| | | // 获取最新工号 |
| | |
| | | |
| | | // 设置工号 |
| | | setSql += ", show_id = " + SqlUtil.addSingleQuotes(Convert.toInt(showId) + 1) |
| | | + ", audit_time = NOW()" |
| | | + ", is_leave_office = 0"; |
| | | |
| | | |
| | | // 购买套餐成功 即 VIP会员,申请入司 为 黄金营销员/城市合伙人 |
| | | MallOrder order = mallOrderService.selectById(memUser.getEquityOrderNo()); |
| | |
| | | Integer gradeId = 0; |
| | | // 判断用是否为普通会员、VIP会员,可直接升级黄金营销员、城市合伙人 |
| | | if (memUser.getMemberGradeId() == EnumMemberGrade.G_1.index || memUser.getMemberGradeId() == EnumMemberGrade.G_2.index) { |
| | | //2024年4月改:购买钻石套餐成为城市合伙人的时间节点:次日、次月、次季度(和人员职级晋升维持设置 一致) |
| | | if (order.getOrderType() == EnumMallGoodsGroupType.GROUP_DIAMOND.index) { |
| | | gradeId = EnumMemberGrade.G_4.index; |
| | | gradeId = EnumMemberGrade.G_3.index; |
| | | setSql +=", upgrade_status = 0"; |
| | | } else if (order.getOrderType() == EnumMallGoodsGroupType.GROUP_GOLD.index) { |
| | | gradeId = EnumMemberGrade.G_3.index; |
| | | setSql +=", upgrade_status = 1"; |
| | | } |
| | | } |
| | | // 判断用是否为黄金营销员,可升级城市合伙人 |
| | | else if (memUser.getMemberGradeId() == EnumMemberGrade.G_3.index) { |
| | | if (order.getOrderType() == EnumMallGoodsGroupType.GROUP_DIAMOND.index) { |
| | | gradeId = EnumMemberGrade.G_4.index; |
| | | } |
| | | } |
| | | // else if (memUser.getMemberGradeId() == EnumMemberGrade.G_3.index) { |
| | | // if (order.getOrderType() == EnumMallGoodsGroupType.GROUP_DIAMOND.index) { |
| | | // gradeId = EnumMemberGrade.G_4.index; |
| | | // } |
| | | // } |
| | | // 其他(城市合伙人、市场总监)不处理 |
| | | |
| | | // 升级、重置品行(处理降级的要重置) |
| | |
| | | + ", member_grade_time = NOW()" |
| | | + ", credit_score = 100"; |
| | | } |
| | | |
| | | // 当用户已申请并通过成为营销员,用户所在城市需显示营销员的城市,营销员的城市取套餐推荐人的所在城市 |
| | | MemUser saleUser = memUserService.selectById(order.getSaleUserId()); |
| | | if (saleUser != null && StrUtil.isNotBlank(saleUser.getCityCode())) { |
| | | String province = StrUtil.sub(saleUser.getCityCode(), 0, 2) + "0000"; |
| | | String city = StrUtil.sub(saleUser.getCityCode(), 0, 4) + "00"; |
| | | String county = saleUser.getCityCode(); |
| | | |
| | | setSql += ", city_code = " + SqlUtil.addSingleQuotes(saleUser.getCityCode()) |
| | | + ", agent_province_code = " + SqlUtil.addSingleQuotes(province) |
| | | + ", agent_city_code = " + SqlUtil.addSingleQuotes(city) |
| | | + ", agent_county_code = " + SqlUtil.addSingleQuotes(county); |
| | | } |
| | | } |
| | | |
| | | // 查询上级 |
| | | MemUserRelation shareUserRelation = memUserRelationService.selectById(order.getSaleUserId()); |
| | | // 更新用户关系表 |
| | | memUserRelationService.insertOrUpdate( |
| | | MemUserRelation.builder() |
| | | .id(userId) |
| | | .parentId(shareUserRelation.getId()) |
| | | .relationPath(shareUserRelation.getRelationPath() + "/" + userId) |
| | | .build() |
| | | ); |
| | | } else if (state == 2) { |
| | | // 重置申请条件 |
| | | setSql += ", is_leave_office = -1"; |
| | | } |
| | | |
| | | boolean flag = memUserService.updateForSet(setSql, new EntityWrapper<MemUser>().eq("id", userId)); |
| | | if (flag) { |
| | | if (state == 2) { |
| | | // 订单材料受赠人,0未申请入司 |
| | | mallOrderService.updateForSet("use_user_id = 0", |
| | | new EntityWrapper<MallOrder>() |
| | | .eq("order_no", memUser.getEquityOrderNo()) |
| | | ); |
| | | } |
| | | // 清除后台通知 |
| | | cleanSystemNotice(memUser.getId()); |
| | | } |
| | |
| | | */ |
| | | @RequestMapping(value = "/detail/{memUserId}") |
| | | public Object detail(@PathVariable("memUserId") Integer memUserId, Model model) { |
| | | boolean admin = ShiroKit.isAdmin(); |
| | | model.addAttribute("isAdmin", admin); |
| | | // 个人信息 |
| | | MemUser memUser = memUserService.selectById(memUserId); |
| | | if (memUser != null) { |
| | |
| | | ); |
| | | } |
| | | map.put("equityUser", equityUser); |
| | | |
| | | MemUser parentUser = memUserRelationService.getParentUserById(memUserId); |
| | | if (parentUser != null) { |
| | | model.addAttribute("equityUserRealName", parentUser.getRealName()); |
| | | model.addAttribute("equityUserCityCode", cityRegionService.getProvinceCityCountyNameByAll(null, parentUser.getCityCode()).stream() |
| | | .map(TCityRegion::getName) |
| | | .collect(Collectors.joining("-"))); |
| | | } |
| | | |
| | | model.addAttribute("item", map); |
| | | } |
| | |
| | | /** |
| | | * 修改品行分 |
| | | */ |
| | | @Permission |
| | | @BussinessLog(value = "营销人员管理-修改品行分") |
| | | @ResponseBody |
| | | @RequestMapping(value = "/editCreditScore") |
| | |
| | | /** |
| | | * 修改职级 |
| | | */ |
| | | @Permission |
| | | @BussinessLog(value = "营销人员管理-修改职级") |
| | | @ResponseBody |
| | | @RequestMapping(value = "/editUserLevel") |
| | | public Object editUserLevel(Integer userId, String memberGradeId) { |
| | | // MemUser memUser = memUserService.selectById(userId); |
| | | // if (memUser == null || memUser.getAuditState() == EnumAuditState.WAIT_AUDIT.index) { |
| | | // return returnByFlag(false, "营销人员状态错误!"); |
| | | // } |
| | | String whereSql = "member_grade_id = " + memberGradeId; |
| | | MemUser memUser = memUserService.selectById(userId); |
| | | if (Objects.nonNull(memUser)) { |
| | | String equityOrderNo = memUser.getEquityOrderNo(); |
| | | MallOrder order = mallOrderService.selectOne(new EntityWrapper<MallOrder>() |
| | | .eq("order_no", equityOrderNo)); |
| | | if (Objects.nonNull(order)) { |
| | | if (order.getOrderType() == 2 && memUser.getMemberGradeId() == 3) { |
| | | whereSql += ", upgrade_status = 1"; |
| | | } |
| | | } |
| | | } |
| | | |
| | | boolean flag = memUserService.updateForSet(whereSql, new EntityWrapper<MemUser>().eq("id", userId)); |
| | | return returnByFlag(flag, null); |
| | | } |
| | | |
| | | @RequestMapping(value = "/openEditCityCode/{userId}") |
| | | public String openEditCityCode(Model model, @PathVariable("userId") Integer userId) { |
| | | // 省市区三级联动 |
| | | List<TCityRegion> cityList = cityRegionService.selectList( |
| | | new EntityWrapper<TCityRegion>() |
| | | .setSqlSelect("code, name") |
| | | .eq("parent_id", 0) |
| | | ); |
| | | model.addAttribute("cityList", cityList); |
| | | |
| | | MemUser item = memUserService.selectOne( |
| | | new EntityWrapper<MemUser>() |
| | | .setSqlSelect("id, city_code") |
| | | .eq("id", userId) |
| | | ); |
| | | |
| | | model.addAttribute("item", item); |
| | | return PREFIX + "edit_city_code.html"; |
| | | } |
| | | |
| | | @Permission |
| | | @BussinessLog(value = "营销人员管理-修改城市", key = "userId") |
| | | @ResponseBody |
| | | @RequestMapping(value = "/editCityCode") |
| | | public Object editCityCode(Integer userId, String cityCode) { |
| | | // 下级用户列表 |
| | | List<MemUserRelation> subUserList = memUserRelationService.selectList( |
| | | new EntityWrapper<MemUserRelation>() |
| | | .setSqlSelect("id, relation_path") |
| | | .like("relation_path", "/" + userId + "/") |
| | | ); |
| | | |
| | | // 获取下级用户ID |
| | | List<Integer> userIdList = subUserList.stream().map(MemUserRelation::getId).collect(Collectors.toList()); |
| | | // 添加自己 |
| | | userIdList.add(userId); |
| | | |
| | | String province = StrUtil.sub(cityCode, 0, 2) + "0000"; |
| | | String city = StrUtil.sub(cityCode, 0, 4) + "00"; |
| | | String county = cityCode; |
| | | |
| | | String whereSql = "city_code = " + SqlUtil.addSingleQuotes(cityCode) |
| | | + ", agent_province_code = " + SqlUtil.addSingleQuotes(province) |
| | | + ", agent_city_code = " + SqlUtil.addSingleQuotes(city) |
| | | + ", agent_county_code = " + SqlUtil.addSingleQuotes(county); |
| | | |
| | | boolean flag = memUserService.updateForSet(whereSql, new EntityWrapper<MemUser>().in("id", userIdList)); |
| | | return returnByFlag(flag, null); |
| | | } |
| | | |
| | | @Permission |
| | | @BussinessLog(value = "营销人员管理-离职") |
| | | @ResponseBody |
| | | @RequestMapping(value = "/updateLeaveOffice") |
| | |
| | | return returnByFlag(flag, null); |
| | | } |
| | | |
| | | |
| | | @Permission |
| | | @ResponseBody |
| | | @BussinessLog(value = "营销人员管理-冻结/解冻") |
| | | @RequestMapping(value = "/updateState") |