| @@ -6,7 +6,12 @@ import com.simple.common.Result; | |||
| import com.simple.common.ResultData; | |||
| import com.simple.domain.po.WxCampaign; | |||
| import com.simple.domain.po.WxCoupon; | |||
| import com.simple.domain.po.WxCouponChannel; | |||
| import com.simple.domain.vo.WxCouponChannelVo; | |||
| import com.simple.enums.EnumCouponChannelType; | |||
| import com.simple.enums.EnumCouponStatus; | |||
| import com.simple.service.WxCampaignService; | |||
| import com.simple.service.WxCouponChannelService; | |||
| import com.simple.service.WxCouponService; | |||
| import io.swagger.annotations.Api; | |||
| import io.swagger.annotations.ApiImplicitParam; | |||
| @@ -29,9 +34,13 @@ public class WxCampaignController extends BaseController | |||
| { | |||
| @Autowired | |||
| private WxCampaignService wxCampaignService; | |||
| @Autowired | |||
| private WxCouponService wxCouponService; | |||
| @Autowired | |||
| private WxCouponChannelService wxCouponChannelService; | |||
| private Logger logger = Logger.getLogger(WxCampaignController.class); | |||
| @ApiOperation("分页列表接口") | |||
| @@ -92,18 +101,13 @@ public class WxCampaignController extends BaseController | |||
| public ResultData findById(Long id) { | |||
| WxCampaign wxCampaign = wxCampaignService.getById(id); | |||
| if (wxCampaign != null) { | |||
| List<Long> list = new ArrayList<>(); | |||
| List<String> templist = JSON.parseArray(wxCampaign.getCouponIds(), String.class); | |||
| for (String temp : templist | |||
| ) { | |||
| list.add(Long.parseLong(temp)); | |||
| } | |||
| WxCoupon wxCoupon = new WxCoupon(); | |||
| wxCoupon.setTenantId(getTenantId()); | |||
| wxCoupon.setIds(list); | |||
| wxCoupon.setStatus(0); | |||
| List<WxCoupon> couponlist = wxCouponService.findList(wxCoupon); | |||
| wxCampaign.setCoupons(couponlist); | |||
| WxCouponChannel wxCouponChannel = new WxCouponChannel(); | |||
| wxCouponChannel.setTenantId(getTenantId()); | |||
| wxCouponChannel.setTargetAd(EnumCouponChannelType.COUPON_CHANNEL_ID_CAMPAIN.getCode()); | |||
| wxCouponChannel.setSubTargetId(wxCampaign.getId()); | |||
| wxCouponChannel.setStatus(0); | |||
| List<WxCouponChannelVo> couponList = wxCouponChannelService.listAPI(wxCouponChannel); | |||
| wxCampaign.setCoupons(couponList); | |||
| } | |||
| return new ResultData(Result.SUCCESS, "查询成功", wxCampaign); | |||
| } | |||
| @@ -6,7 +6,11 @@ import com.simple.common.Result; | |||
| import com.simple.common.ResultData; | |||
| import com.simple.domain.po.WxCampaign; | |||
| import com.simple.domain.po.WxCoupon; | |||
| import com.simple.domain.po.WxCouponChannel; | |||
| import com.simple.domain.vo.WxCouponChannelVo; | |||
| import com.simple.enums.EnumCouponChannelType; | |||
| import com.simple.service.WxCampaignService; | |||
| import com.simple.service.WxCouponChannelService; | |||
| import com.simple.service.WxCouponService; | |||
| import io.swagger.annotations.Api; | |||
| import io.swagger.annotations.ApiImplicitParam; | |||
| @@ -31,6 +35,8 @@ public class WxCampaignController extends BaseController | |||
| private WxCampaignService wxCampaignService; | |||
| @Autowired | |||
| private WxCouponService wxCouponService; | |||
| @Autowired | |||
| private WxCouponChannelService wxCouponChannelService; | |||
| private Logger logger = Logger.getLogger(WxCampaignController.class); | |||
| @@ -54,18 +60,13 @@ public class WxCampaignController extends BaseController | |||
| public ResultData findById(Long id) { | |||
| WxCampaign wxCampaign = wxCampaignService.getById(id); | |||
| if (wxCampaign != null) { | |||
| List<Long> list = new ArrayList<>(); | |||
| List<String> templist = JSON.parseArray(wxCampaign.getCouponIds(), String.class); | |||
| for (String temp : templist | |||
| ) { | |||
| list.add(Long.parseLong(temp)); | |||
| } | |||
| WxCoupon wxCoupon = new WxCoupon(); | |||
| wxCoupon.setTenantId(getTenantId()); | |||
| wxCoupon.setIds(list); | |||
| wxCoupon.setStatus(0); | |||
| List<WxCoupon> couponlist = wxCouponService.findList(wxCoupon); | |||
| wxCampaign.setCoupons(couponlist); | |||
| WxCouponChannel wxCouponChannel = new WxCouponChannel(); | |||
| wxCouponChannel.setTenantId(getTenantId()); | |||
| wxCouponChannel.setTargetAd(EnumCouponChannelType.COUPON_CHANNEL_ID_CAMPAIN.getCode()); | |||
| wxCouponChannel.setSubTargetId(wxCampaign.getId()); | |||
| wxCouponChannel.setStatus(0); | |||
| List<WxCouponChannelVo> couponList = wxCouponChannelService.listAPI(wxCouponChannel); | |||
| wxCampaign.setCoupons(couponList); | |||
| } | |||
| return new ResultData(Result.SUCCESS, "查询成功", wxCampaign); | |||
| } | |||
| @@ -71,6 +71,7 @@ public enum ErrorCode{ | |||
| COUPON_IS_NOT_FREE(2021, "券不免费"), | |||
| COUPON_IS_TAKE_OFF(2022, "此券已下架"), | |||
| COUPON_CHANNEL_IS_EXISTED(2023, "券已投放过"), | |||
| /** | |||
| * 车流 2040 | |||
| */ | |||
| @@ -1,5 +1,7 @@ | |||
| package com.simple.domain.po; | |||
| import com.simple.domain.vo.WxCouponChannelVo; | |||
| import javax.persistence.*; | |||
| import java.util.*; | |||
| import java.math.*; | |||
| @@ -20,13 +22,13 @@ public class WxCampaign implements Serializable { | |||
| @Transient | |||
| protected String sortColumns; | |||
| @Transient | |||
| protected List<WxCoupon> coupons; | |||
| protected List<WxCouponChannelVo> coupons; | |||
| public List<WxCoupon> getCoupons() { | |||
| public List<WxCouponChannelVo> getCoupons() { | |||
| return coupons; | |||
| } | |||
| public void setCoupons(List<WxCoupon> coupons) { | |||
| public void setCoupons(List<WxCouponChannelVo> coupons) { | |||
| this.coupons = coupons; | |||
| } | |||
| @@ -211,23 +213,23 @@ public class WxCampaign implements Serializable { | |||
| public static enum Field | |||
| { | |||
| Id_ASC("`id` ASC"),Id_DESC("`id` DESC") | |||
| ,TenantId_ASC("`tenantId` ASC"),TenantId_DESC("`tenantId` DESC") | |||
| ,CoverImg_ASC("`coverImg` ASC"),CoverImg_DESC("`coverImg` DESC") | |||
| ,TenantId_ASC("`tenant_id` ASC"),TenantId_DESC("`tenant_id` DESC") | |||
| ,CoverImg_ASC("`cover_img` ASC"),CoverImg_DESC("`cover_img` DESC") | |||
| ,Title_ASC("`title` ASC"),Title_DESC("`title` DESC") | |||
| ,SubTitle_ASC("`subTitle` ASC"),SubTitle_DESC("`subTitle` DESC") | |||
| ,UsePrice_ASC("`usePrice` ASC"),UsePrice_DESC("`usePrice` DESC") | |||
| ,DiscountPrice_ASC("`discountPrice` ASC"),DiscountPrice_DESC("`discountPrice` DESC") | |||
| ,SubTitle_ASC("`sub_title` ASC"),SubTitle_DESC("`sub_title` DESC") | |||
| ,UsePrice_ASC("`use_price` ASC"),UsePrice_DESC("`use_price` DESC") | |||
| ,DiscountPrice_ASC("`discount_price` ASC"),DiscountPrice_DESC("`discount_price` DESC") | |||
| ,Detail_ASC("`detail` ASC"),Detail_DESC("`detail` DESC") | |||
| ,ValidStartDate_ASC("`validStartDate` ASC"),ValidStartDate_DESC("`validStartDate` DESC") | |||
| ,ValidEndDate_ASC("`validEndDate` ASC"),ValidEndDate_DESC("`validEndDate` DESC") | |||
| ,ImgDetail_ASC("`imgDetail` ASC"),ImgDetail_DESC("`imgDetail` DESC") | |||
| ,ValidStartDate_ASC("`valid_start_date` ASC"),ValidStartDate_DESC("`valid_start_date` DESC") | |||
| ,ValidEndDate_ASC("`valid_end_date` ASC"),ValidEndDate_DESC("`valid_end_date` DESC") | |||
| ,ImgDetail_ASC("`img_detail` ASC"),ImgDetail_DESC("`img_detail` DESC") | |||
| ,Type_ASC("`type` ASC"),Type_DESC("`type` DESC") | |||
| ,CouponIds_ASC("`couponIds` ASC"),CouponIds_DESC("`couponIds` DESC") | |||
| ,MechantId_ASC("`mechantId` ASC"),MechantId_DESC("`mechantId` DESC") | |||
| ,SortNum_ASC("`sortNum` ASC"),SortNum_DESC("`sortNum` DESC") | |||
| ,CouponIds_ASC("`coupon_ids` ASC"),CouponIds_DESC("`coupon_ids` DESC") | |||
| ,MechantId_ASC("`mechant_id` ASC"),MechantId_DESC("`mechantId` DESC") | |||
| ,SortNum_ASC("`sort_num` ASC"),SortNum_DESC("`sortNum` DESC") | |||
| ,Status_ASC("`status` ASC"),Status_DESC("`status` DESC") | |||
| ,CreateTime_ASC("`createTime` ASC"),CreateTime_DESC("`createTime` DESC") | |||
| ,UpdateTime_ASC("`updateTime` ASC"),UpdateTime_DESC("`updateTime` DESC") | |||
| ,CreateTime_ASC("`create_time` ASC"),CreateTime_DESC("`create_time` DESC") | |||
| ,UpdateTime_ASC("`update_time` ASC"),UpdateTime_DESC("`update_time` DESC") | |||
| ; | |||
| private String value; | |||
| Field(String value){ | |||
| @@ -260,7 +262,7 @@ public class WxCampaign implements Serializable { | |||
| sb.append(","); | |||
| sb.append(fields[k].toString()); | |||
| } | |||
| this.sortColumns = sb.toString(); | |||
| } | |||
| public void setSortColumns(String sortColumns) | |||
| @@ -17,8 +17,6 @@ public class WxCouponChannel implements Serializable { | |||
| @Transient | |||
| protected List<Long> ids; | |||
| @Transient | |||
| protected List<Long> couponIds; | |||
| @Transient | |||
| protected String sortColumns; | |||
| @@ -44,6 +42,15 @@ public class WxCouponChannel implements Serializable { | |||
| } | |||
| @Transient | |||
| protected List<Long> couponIds; | |||
| public List<Long> getCouponIds() { | |||
| return couponIds; | |||
| } | |||
| public void setCouponIds(List<Long> couponIds) { | |||
| this.couponIds = couponIds; | |||
| } | |||
| /*租户ID**/ | |||
| @io.swagger.annotations.ApiModelProperty(value="租户ID",name="tenantId") | |||
| @@ -82,6 +89,11 @@ public class WxCouponChannel implements Serializable { | |||
| /*更新时间**/ | |||
| @io.swagger.annotations.ApiModelProperty(value="更新时间",name="updateDate") | |||
| private Date updateDate; | |||
| /*更新时间**/ | |||
| @io.swagger.annotations.ApiModelProperty(value="子频道ID",name="subTargetId") | |||
| private Long subTargetId; | |||
| public String getTenantId() { | |||
| return tenantId; | |||
| } | |||
| @@ -154,12 +166,13 @@ public class WxCouponChannel implements Serializable { | |||
| public void setUpdateDate(Date _updateDate) { | |||
| updateDate = _updateDate; | |||
| } | |||
| public List<Long> getCouponIds() { | |||
| return couponIds; | |||
| } | |||
| public void setCouponIds(List<Long> couponIds) { | |||
| this.couponIds = couponIds; | |||
| public Long getSubTargetId() { | |||
| return subTargetId; | |||
| } | |||
| public void setSubTargetId(Long subTargetId) { | |||
| this.subTargetId = subTargetId; | |||
| } | |||
| @@ -0,0 +1,39 @@ | |||
| package com.simple.enums; | |||
| /** | |||
| * Created by Stormeye on 2018/08/09. | |||
| */ | |||
| public enum EnumCouponChannelType { | |||
| COUPON_CHANNEL_ID_LIST(1, "列表"), | |||
| COUPON_CHANNEL_ID_TIMED(2, "限时抢购"), | |||
| COUPON_CHANNEL_ID_CAMPAIN(3, "幻灯片"), | |||
| ; | |||
| ; | |||
| public static EnumCouponChannelType getEnum(Integer code) { | |||
| for (EnumCouponChannelType value : values()) { | |||
| if (value.getCode().equals(code)) { | |||
| return value; | |||
| } | |||
| } | |||
| return null; | |||
| } | |||
| private Integer code; | |||
| private String message; | |||
| EnumCouponChannelType(Integer code, String message) { | |||
| this.code = code; | |||
| this.message = message; | |||
| } | |||
| public Integer getCode() { | |||
| return code; | |||
| } | |||
| public String getMessage() { | |||
| return message; | |||
| } | |||
| } | |||
| @@ -6,6 +6,7 @@ import com.simple.domain.po.WxCouponChannel; | |||
| import com.simple.domain.vo.WxCouponChannelVo; | |||
| import java.util.Date; | |||
| import java.util.List; | |||
| public interface WxCouponChannelService { | |||
| @@ -20,7 +21,9 @@ public interface WxCouponChannelService { | |||
| PageInfo<WxCouponChannel> listAsPage(WxCouponChannel record, Integer pageIndex, Integer pageSize); | |||
| PageInfo<WxCouponChannelVo> listPageCAPI(WxCouponChannel record, Integer pageIndex, Integer pageSize); | |||
| List<WxCouponChannelVo> listAPI(WxCouponChannel record); | |||
| /** | |||
| * 根据Id获得实体 | |||
| * | |||
| @@ -1,13 +1,29 @@ | |||
| package com.simple.service.impl; | |||
| import com.alibaba.fastjson.JSONArray; | |||
| import com.github.pagehelper.PageHelper; | |||
| import com.github.pagehelper.PageInfo; | |||
| import com.simple.common.ErrorCode; | |||
| import com.simple.common.IdWorker; | |||
| import com.simple.domain.po.WxCampaign; | |||
| import com.simple.domain.po.WxCoupon; | |||
| import com.simple.domain.po.WxCouponChannel; | |||
| import com.simple.enums.EnumCouponChannelStatus; | |||
| import com.simple.enums.EnumCouponChannelType; | |||
| import com.simple.enums.EnumCouponStatus; | |||
| import com.simple.exception.MallinkException; | |||
| import com.simple.mapper.WxCampaignMapper; | |||
| import com.simple.mapper.WxCouponChannelMapper; | |||
| import com.simple.service.WxCampaignService; | |||
| import com.simple.service.WxCouponChannelService; | |||
| import com.simple.service.WxCouponService; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Service; | |||
| import org.springframework.transaction.annotation.Propagation; | |||
| import org.springframework.transaction.annotation.Transactional; | |||
| import java.util.Date; | |||
| import java.util.List; | |||
| @Service | |||
| public class WxCampaignServiceImpl implements WxCampaignService { | |||
| @@ -15,6 +31,14 @@ public class WxCampaignServiceImpl implements WxCampaignService { | |||
| @Autowired | |||
| WxCampaignMapper wxCampaignMapper; | |||
| @Autowired | |||
| WxCouponChannelMapper wxCouponChannelMapper; | |||
| @Autowired | |||
| WxCouponService wxCouponService; | |||
| @Autowired | |||
| WxCouponChannelService wxCouponChannelService; | |||
| @Override | |||
| public PageInfo<WxCampaign> listAsPage(WxCampaign record, Integer pageIndex, Integer pageSize) { | |||
| @@ -26,16 +50,87 @@ public class WxCampaignServiceImpl implements WxCampaignService { | |||
| return wxCampaignMapper.selectByPrimaryKey(id); | |||
| } | |||
| @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) | |||
| @Override | |||
| public void saveOrUpdate(WxCampaign record) { | |||
| if (record.getId() == null) { | |||
| //record.setId(UUID.randomUUID().toString().replaceAll("-", "")); | |||
| IdWorker idWorker = new IdWorker(0, 0); | |||
| record.setId(idWorker.nextId()); | |||
| wxCampaignMapper.insertSelective(record); | |||
| } else { | |||
| wxCampaignMapper.updateByPrimaryKeySelective(record); | |||
| } | |||
| if (record.getStatus() == 0) | |||
| addOrUpdateBatch(JSONArray.parseArray(record.getCouponIds(),String.class),record); | |||
| else | |||
| delBatch(record); | |||
| } | |||
| public void delBatch(WxCampaign record) { | |||
| WxCouponChannel wxCouponChannelQuery = new WxCouponChannel(); | |||
| wxCouponChannelQuery.setTenantId(record.getTenantId()); | |||
| wxCouponChannelQuery.setTargetAd(EnumCouponChannelType.COUPON_CHANNEL_ID_CAMPAIN.getCode()); | |||
| wxCouponChannelQuery.setSubTargetId(record.getId()); | |||
| List<WxCouponChannel> wxCouponChannels = wxCouponChannelMapper.findList(wxCouponChannelQuery); | |||
| if (wxCouponChannels.size() > 0) { | |||
| for (WxCouponChannel ch : wxCouponChannels) { | |||
| ch.setStatus(EnumCouponChannelStatus.STATUS_TAKE_OFFF.getCode()); | |||
| wxCouponChannelMapper.updateByPrimaryKeySelective(ch); | |||
| } | |||
| } | |||
| } | |||
| public void addOrUpdateBatch(List<String> ids, WxCampaign record) { | |||
| for (String couponIdStr:ids) { | |||
| Long couponId = Long.parseLong(couponIdStr); | |||
| saveOrUpdateCouponChannel(couponId,record); | |||
| } | |||
| } | |||
| public void saveOrUpdateCouponChannel(Long couponId, WxCampaign record){ | |||
| WxCoupon wxCoupon = wxCouponService.getById(couponId); | |||
| if (wxCoupon == null) { | |||
| throw new MallinkException(ErrorCode.COUPON_IS_EMPTY); | |||
| } | |||
| if (wxCoupon.getStatus() != EnumCouponStatus.COUPON_STATUS_THROW_IN.getCode()) { | |||
| throw new MallinkException(ErrorCode.COUPON_IS_TAKE_OFF); | |||
| } | |||
| if (wxCoupon.getValidEndDate() != null && wxCoupon.getValidEndDate().after(new Date())) { | |||
| throw new MallinkException(ErrorCode.COUPON_IS_TAKE_OFF); | |||
| } | |||
| WxCouponChannel wxCouponChannelQuery = new WxCouponChannel(); | |||
| wxCouponChannelQuery.setTenantId(record.getTenantId()); | |||
| wxCouponChannelQuery.setCouponId(couponId); | |||
| wxCouponChannelQuery.setTargetAd(EnumCouponChannelType.COUPON_CHANNEL_ID_CAMPAIN.getCode()); | |||
| wxCouponChannelQuery.setSubTargetId(record.getId()); | |||
| List<WxCouponChannel> wxCouponChannels = wxCouponChannelMapper.findList(wxCouponChannelQuery); | |||
| if(wxCouponChannels.size()>0){ | |||
| if(wxCouponChannels.get(0).getStatus() == EnumCouponChannelStatus.STATUS_TAKE_OFFF.getCode()) { | |||
| wxCouponChannels.get(0).setStatus(EnumCouponChannelStatus.STATUS_THROW_IN.getCode()); | |||
| wxCouponChannelMapper.updateByPrimaryKeySelective(wxCouponChannels.get(0)); | |||
| } | |||
| } | |||
| else { | |||
| WxCouponChannel wxCouponChannel = new WxCouponChannel(); | |||
| wxCouponChannel.setStatus(EnumCouponChannelStatus.STATUS_THROW_IN.getCode()); | |||
| wxCouponChannel.setCouponId(couponId); | |||
| wxCouponChannel.setMerchantId(wxCoupon.getMerchantId()); | |||
| wxCouponChannel.setType(wxCoupon.getType()); | |||
| wxCouponChannel.setTargetAd(EnumCouponChannelType.COUPON_CHANNEL_ID_CAMPAIN.getCode()); | |||
| wxCouponChannel.setTenantId(wxCoupon.getTenantId()); | |||
| wxCouponChannel.setBusiness(wxCoupon.getBusiness()); | |||
| wxCouponChannel.setTitle(wxCoupon.getTitle()); | |||
| wxCouponChannel.setSubTargetId(record.getId()); | |||
| final IdWorker idWorker = IdWorker.get(); | |||
| wxCouponChannel.setId(idWorker.nextId()); | |||
| wxCouponChannelMapper.insertSelective(wxCouponChannel); | |||
| } | |||
| } | |||
| @Override | |||
| @@ -165,5 +165,24 @@ public class WxCouponChannelServiceImpl implements WxCouponChannelService { | |||
| return new PageInfo<>(wxCouponChannelVoList); | |||
| } | |||
| @Override | |||
| public List<WxCouponChannelVo> listAPI(WxCouponChannel record) { | |||
| List<WxCouponChannelVo> wxCouponChannelVoList = new ArrayList<>(); | |||
| wxCouponChannelVoList = wxCouponChannelMapper.findVoList(record); | |||
| if(wxCouponChannelVoList.isEmpty()){ | |||
| return wxCouponChannelVoList; | |||
| } | |||
| List<Long> couponIds = wxCouponChannelVoList.stream().map(p->p.getCouponId()).distinct().collect(Collectors.toList()); | |||
| WxCoupon wxCoupon = new WxCoupon(); | |||
| wxCoupon.setIds(couponIds); | |||
| List<WxCoupon> wxCoupons = wxCouponService.findList(wxCoupon); | |||
| Map<Long,WxCoupon> couponNamesMap = wxCoupons.stream().collect(Collectors.toMap(WxCoupon::getId,p->p)); | |||
| for (WxCouponChannelVo wxcouponVo:wxCouponChannelVoList) { | |||
| if(couponNamesMap.get(wxcouponVo.getCouponId())!=null){ | |||
| wxcouponVo.setWxCoupon(couponNamesMap.get(wxcouponVo.getCouponId())); | |||
| } | |||
| } | |||
| return wxCouponChannelVoList; | |||
| } | |||
| } | |||
| @@ -15,10 +15,11 @@ | |||
| <result column="status" jdbcType="INTEGER" property="status" /> | |||
| <result column="create_date" jdbcType="TIMESTAMP" property="createDate" /> | |||
| <result column="update_date" jdbcType="TIMESTAMP" property="updateDate" /> | |||
| <result column="sub_target_id" jdbcType="BIGINT" property="subTargetId" /> | |||
| </resultMap> | |||
| <sql id="allColumns"> | |||
| `id`,`tenant_id`,`merchant_id`,`coupon_id`,`coupon_status`,`type`,`title`,`target_ad`,`business`,`begin_time`,`end_time`,`status`,`create_date`,`update_date` | |||
| `id`,`tenant_id`,`merchant_id`,`coupon_id`,`coupon_status`,`type`,`title`,`target_ad`,`business`,`begin_time`,`end_time`,`status`,`create_date`,`update_date`,`sub_target_id` | |||
| </sql> | |||
| <sql id="dynamicWhereConditions"> | |||
| @@ -88,6 +89,10 @@ | |||
| <if test=" null != updateDate "> | |||
| and `update_date` = #{updateDate} | |||
| </if> | |||
| <if test=" null != subTargetId "> | |||
| and `sub_target_id` = #{subTargetId} | |||
| </if> | |||
| <if test=" null != ids "> | |||
| and id in | |||
| @@ -137,6 +142,7 @@ | |||
| <result column="business" jdbcType="VARCHAR" property="business" /> | |||
| <result column="create_date" jdbcType="TIMESTAMP" property="createDate" /> | |||
| <result column="update_date" jdbcType="TIMESTAMP" property="updateDate" /> | |||
| <result column="sub_target_id" jdbcType="BIGINT" property="subTargetId" /> | |||
| </resultMap> | |||