mirror of
https://gitee.com/dromara/dax-pay
synced 2026-08-13 07:45:41 +08:00
feat(merchant): 新增门店信息管理(建表/状态枚举/双Controller/i18n)
This commit is contained in:
@@ -99,3 +99,57 @@ COMMENT ON COLUMN notify_message.version IS '版本号(乐观锁)';
|
||||
COMMENT ON COLUMN notify_message.deleted IS '逻辑删除标志';
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_notify_message_user ON notify_message (user_id, deleted, is_read);
|
||||
|
||||
-- ===================================
|
||||
-- 商户门店(商户物理经营场所)
|
||||
-- ===================================
|
||||
CREATE TABLE IF NOT EXISTS mch_store_info (
|
||||
id bigint NOT NULL,
|
||||
mch_no varchar(32) NOT NULL,
|
||||
store_no varchar(32) NOT NULL,
|
||||
store_name varchar(128) NOT NULL,
|
||||
contact_phone varchar(32),
|
||||
logo_url varchar(512),
|
||||
facade_url varchar(512),
|
||||
interior_url varchar(512),
|
||||
region_code varchar(12),
|
||||
address varchar(256),
|
||||
longitude numeric(10,7),
|
||||
latitude numeric(10,7),
|
||||
status varchar(16) NOT NULL DEFAULT 'enable',
|
||||
remark varchar(512),
|
||||
creator bigint,
|
||||
create_time timestamptz(6),
|
||||
last_modifier bigint,
|
||||
last_modified_time timestamptz(6),
|
||||
version int NOT NULL DEFAULT 0,
|
||||
deleted boolean NOT NULL DEFAULT false,
|
||||
CONSTRAINT mch_store_info_pkey PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE mch_store_info IS '商户门店(商户物理经营场所)';
|
||||
COMMENT ON COLUMN mch_store_info.id IS '主键';
|
||||
COMMENT ON COLUMN mch_store_info.mch_no IS '商户号';
|
||||
COMMENT ON COLUMN mch_store_info.store_no IS '门店号(系统生成, 唯一)';
|
||||
COMMENT ON COLUMN mch_store_info.store_name IS '门店名称';
|
||||
COMMENT ON COLUMN mch_store_info.contact_phone IS '联系人电话';
|
||||
COMMENT ON COLUMN mch_store_info.logo_url IS '门店LOGO';
|
||||
COMMENT ON COLUMN mch_store_info.facade_url IS '门头照';
|
||||
COMMENT ON COLUMN mch_store_info.interior_url IS '门店内景照';
|
||||
COMMENT ON COLUMN mch_store_info.region_code IS '行政区划代码(区县级)';
|
||||
COMMENT ON COLUMN mch_store_info.address IS '详细地址';
|
||||
COMMENT ON COLUMN mch_store_info.longitude IS '经度';
|
||||
COMMENT ON COLUMN mch_store_info.latitude IS '纬度';
|
||||
COMMENT ON COLUMN mch_store_info.status IS '状态(enable启用/disabled停用)';
|
||||
COMMENT ON COLUMN mch_store_info.remark IS '备注';
|
||||
COMMENT ON COLUMN mch_store_info.creator IS '创建人ID';
|
||||
COMMENT ON COLUMN mch_store_info.create_time IS '创建时间';
|
||||
COMMENT ON COLUMN mch_store_info.last_modifier IS '最后修改人ID';
|
||||
COMMENT ON COLUMN mch_store_info.last_modified_time IS '最后修改时间';
|
||||
COMMENT ON COLUMN mch_store_info.version IS '版本号(乐观锁)';
|
||||
COMMENT ON COLUMN mch_store_info.deleted IS '逻辑删除标志';
|
||||
|
||||
-- 门店号唯一索引
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS uk_mch_store_info_store_no ON mch_store_info (store_no);
|
||||
-- 商户号查询索引
|
||||
CREATE INDEX IF NOT EXISTS idx_mch_store_info_mch_no ON mch_store_info (mch_no, deleted);
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package cn.daxpay.open.payment.admin.controller.merchant.store;
|
||||
|
||||
import cn.daxpay.open.payment.merchant.param.store.MchStoreInfoParam;
|
||||
import cn.daxpay.open.payment.merchant.param.store.MchStoreInfoQuery;
|
||||
import cn.daxpay.open.payment.merchant.result.store.MchStoreInfoResult;
|
||||
import cn.daxpay.open.payment.merchant.service.store.MchStoreInfoService;
|
||||
import cn.daxpay.open.platform.core.annotation.PermCode;
|
||||
import cn.daxpay.open.platform.core.rest.Res;
|
||||
import cn.daxpay.open.platform.core.rest.param.PageParam;
|
||||
import cn.daxpay.open.platform.core.rest.result.PageResult;
|
||||
import cn.daxpay.open.platform.core.rest.result.Result;
|
||||
import cn.daxpay.open.platform.core.util.ValidationUtil;
|
||||
import cn.daxpay.open.platform.core.validation.ValidationGroup;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/// 门店信息管理(管理端)
|
||||
@PermCode(menuCode = "payment:merchant:store")
|
||||
@Validated
|
||||
@Tag(name = "门店信息管理(管理端)")
|
||||
@RestController
|
||||
@RequestMapping("/admin/mch/store")
|
||||
@RequiredArgsConstructor
|
||||
public class MchStoreInfoAdminController {
|
||||
private final MchStoreInfoService mchStoreInfoService;
|
||||
|
||||
@PermCode(code = "add", nameCn = "门店新增", nameEn = "Store Add")
|
||||
@Operation(summary = "新增门店")
|
||||
@PostMapping("/add")
|
||||
public Result<Void> add(@RequestBody @Validated(ValidationGroup.add.class) MchStoreInfoParam param) {
|
||||
ValidationUtil.validateParam(param, ValidationGroup.add.class);
|
||||
mchStoreInfoService.add(param);
|
||||
return Res.ok();
|
||||
}
|
||||
|
||||
@PermCode(code = "edit", nameCn = "门店编辑", nameEn = "Store Edit")
|
||||
@Operation(summary = "修改门店")
|
||||
@PostMapping("/update")
|
||||
public Result<Void> update(@RequestBody @Validated(ValidationGroup.edit.class) MchStoreInfoParam param) {
|
||||
ValidationUtil.validateParam(param, ValidationGroup.edit.class);
|
||||
mchStoreInfoService.update(param);
|
||||
return Res.ok();
|
||||
}
|
||||
|
||||
@PermCode(code = "view", nameCn = "门店查看", nameEn = "Store View")
|
||||
@Operation(summary = "门店分页")
|
||||
@GetMapping("/page")
|
||||
public Result<PageResult<MchStoreInfoResult>> page(PageParam pageParam, MchStoreInfoQuery query) {
|
||||
return Res.ok(mchStoreInfoService.page(pageParam, query));
|
||||
}
|
||||
|
||||
@PermCode(code = "view", nameCn = "门店查看", nameEn = "Store View")
|
||||
@Operation(summary = "根据id查询门店")
|
||||
@GetMapping("/get")
|
||||
public Result<MchStoreInfoResult> findById(@NotNull(message = "{validation.field.id.notNull}") Long id) {
|
||||
return Res.ok(mchStoreInfoService.findById(id));
|
||||
}
|
||||
|
||||
@PermCode(code = "delete", nameCn = "门店删除", nameEn = "Store Delete")
|
||||
@Operation(summary = "删除门店")
|
||||
@PostMapping("/delete")
|
||||
public Result<Void> delete(@NotNull(message = "{validation.field.id.notNull}") Long id) {
|
||||
mchStoreInfoService.delete(id);
|
||||
return Res.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package cn.daxpay.open.payment.merchant.controller.store;
|
||||
|
||||
import cn.daxpay.open.payment.merchant.param.store.MchStoreInfoParam;
|
||||
import cn.daxpay.open.payment.merchant.param.store.MchStoreInfoQuery;
|
||||
import cn.daxpay.open.payment.merchant.result.store.MchStoreInfoResult;
|
||||
import cn.daxpay.open.payment.merchant.service.store.MchStoreInfoService;
|
||||
import cn.daxpay.open.platform.core.rest.Res;
|
||||
import cn.daxpay.open.platform.core.rest.param.PageParam;
|
||||
import cn.daxpay.open.platform.core.rest.result.PageResult;
|
||||
import cn.daxpay.open.platform.core.rest.result.Result;
|
||||
import cn.daxpay.open.platform.core.validation.ValidationGroup;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/// # 门店信息管理
|
||||
///
|
||||
@Validated
|
||||
@Tag(name = "门店信息管理")
|
||||
@RestController
|
||||
@RequestMapping("/mch/store")
|
||||
@RequiredArgsConstructor
|
||||
public class MchStoreInfoController {
|
||||
private final MchStoreInfoService mchStoreInfoService;
|
||||
|
||||
@Operation(summary = "新增门店")
|
||||
@PostMapping("/add")
|
||||
public Result<Void> add(@RequestBody @Validated(ValidationGroup.add.class) MchStoreInfoParam param) {
|
||||
mchStoreInfoService.add(param);
|
||||
return Res.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "修改门店")
|
||||
@PostMapping("/update")
|
||||
public Result<Void> update(@RequestBody @Validated(ValidationGroup.edit.class) MchStoreInfoParam param) {
|
||||
mchStoreInfoService.update(param);
|
||||
return Res.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "门店分页")
|
||||
@GetMapping("/page")
|
||||
public Result<PageResult<MchStoreInfoResult>> page(PageParam pageParam, MchStoreInfoQuery query) {
|
||||
return Res.ok(mchStoreInfoService.page(pageParam, query));
|
||||
}
|
||||
|
||||
@Operation(summary = "门店列表")
|
||||
@GetMapping("/list")
|
||||
public Result<List<MchStoreInfoResult>> list() {
|
||||
return Res.ok(mchStoreInfoService.list());
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询门店")
|
||||
@GetMapping("/get")
|
||||
public Result<MchStoreInfoResult> findById(@NotNull(message = "{validation.field.id.notNull}") Long id) {
|
||||
return Res.ok(mchStoreInfoService.findById(id));
|
||||
}
|
||||
|
||||
@Operation(summary = "删除门店")
|
||||
@PostMapping("/delete")
|
||||
public Result<Void> delete(@NotNull(message = "{validation.field.id.notNull}") Long id) {
|
||||
mchStoreInfoService.delete(id);
|
||||
return Res.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package cn.daxpay.open.payment.merchant.convert.store;
|
||||
|
||||
import cn.daxpay.open.payment.merchant.entity.store.MchStoreInfo;
|
||||
import cn.daxpay.open.payment.merchant.param.store.MchStoreInfoParam;
|
||||
import cn.daxpay.open.payment.merchant.result.store.MchStoreInfoResult;
|
||||
import org.mapstruct.BeanMapping;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.MappingTarget;
|
||||
import org.mapstruct.NullValuePropertyMappingStrategy;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/// # 门店信息转换
|
||||
///
|
||||
@Mapper
|
||||
public interface MchStoreInfoConvert {
|
||||
MchStoreInfoConvert CONVERT = Mappers.getMapper(MchStoreInfoConvert.class);
|
||||
|
||||
MchStoreInfoResult toResult(MchStoreInfo entity);
|
||||
|
||||
MchStoreInfo toEntity(MchStoreInfoParam param);
|
||||
|
||||
@BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
|
||||
void copy(MchStoreInfoParam param, @MappingTarget MchStoreInfo mchStore);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package cn.daxpay.open.payment.merchant.dao.store;
|
||||
|
||||
import cn.daxpay.open.payment.merchant.entity.store.MchStoreInfo;
|
||||
import cn.daxpay.open.payment.merchant.param.store.MchStoreInfoQuery;
|
||||
import cn.daxpay.open.platform.common.mybatisplus.impl.BaseManager;
|
||||
import cn.daxpay.open.platform.common.mybatisplus.query.generator.QueryGenerator;
|
||||
import cn.daxpay.open.platform.common.mybatisplus.util.MpUtil;
|
||||
import cn.daxpay.open.platform.core.rest.param.PageParam;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/// # 门店信息管理
|
||||
///
|
||||
@Slf4j
|
||||
@Repository
|
||||
@RequiredArgsConstructor
|
||||
public class MchStoreInfoManager extends BaseManager<MchStoreInfoMapper, MchStoreInfo> {
|
||||
|
||||
/// 根据门店号查询
|
||||
public Optional<MchStoreInfo> findByStoreNo(String storeNo) {
|
||||
return this.findByField(MchStoreInfo::getStoreNo, storeNo);
|
||||
}
|
||||
|
||||
/// 判断门店号是否存在
|
||||
public boolean existsByStoreNo(String storeNo) {
|
||||
return existedByField(MchStoreInfo::getStoreNo, storeNo);
|
||||
}
|
||||
|
||||
/// 分页
|
||||
public Page<MchStoreInfo> page(PageParam pageParam, MchStoreInfoQuery query) {
|
||||
Page<MchStoreInfo> mpPage = MpUtil.getMpPage(pageParam);
|
||||
QueryWrapper<MchStoreInfo> wrapper = QueryGenerator.generator(query);
|
||||
return this.page(mpPage, wrapper);
|
||||
}
|
||||
|
||||
/// 根据商户号查询所有门店
|
||||
public List<MchStoreInfo> findAllByMchNo(String mchNo) {
|
||||
return this.findAllByField(MchStoreInfo::getMchNo, mchNo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package cn.daxpay.open.payment.merchant.dao.store;
|
||||
|
||||
import cn.daxpay.open.payment.merchant.entity.store.MchStoreInfo;
|
||||
import com.github.yulichang.base.MPJBaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/// # 门店信息
|
||||
///
|
||||
@Mapper
|
||||
public interface MchStoreInfoMapper extends MPJBaseMapper<MchStoreInfo> {
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package cn.daxpay.open.payment.merchant.entity.store;
|
||||
|
||||
import cn.daxpay.open.payment.common.entity.merchant.MchBaseEntity;
|
||||
import cn.daxpay.open.payment.merchant.convert.store.MchStoreInfoConvert;
|
||||
import cn.daxpay.open.payment.merchant.result.store.MchStoreInfoResult;
|
||||
import cn.daxpay.open.platform.common.mybatisplus.function.ToResult;
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.FieldStrategy;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import lombok.experimental.FieldNameConstants;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/// # 门店信息
|
||||
///
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@FieldNameConstants
|
||||
@Accessors(chain = true)
|
||||
@TableName("mch_store_info")
|
||||
public class MchStoreInfo extends MchBaseEntity implements ToResult<MchStoreInfoResult> {
|
||||
|
||||
/// 门店号
|
||||
@TableField(updateStrategy = FieldStrategy.NEVER, fill = FieldFill.INSERT)
|
||||
private String storeNo;
|
||||
|
||||
/// 门店名称
|
||||
private String storeName;
|
||||
|
||||
/// 联系人电话
|
||||
private String contactPhone;
|
||||
|
||||
/// 门店LOGO
|
||||
private String logoUrl;
|
||||
|
||||
/// 门头照
|
||||
private String facadeUrl;
|
||||
|
||||
/// 门店内景照
|
||||
private String interiorUrl;
|
||||
|
||||
/// 行政区划代码
|
||||
private String regionCode;
|
||||
|
||||
/// 详细地址
|
||||
private String address;
|
||||
|
||||
/// 经度
|
||||
private BigDecimal longitude;
|
||||
|
||||
/// 纬度
|
||||
private BigDecimal latitude;
|
||||
|
||||
/// 状态
|
||||
/// @see cn.daxpay.open.platform.core.enums.merchant.StoreStatusEnum
|
||||
private String status;
|
||||
|
||||
/// 备注
|
||||
private String remark;
|
||||
|
||||
@Override
|
||||
public MchStoreInfoResult toResult() {
|
||||
return MchStoreInfoConvert.CONVERT.toResult(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package cn.daxpay.open.payment.merchant.param.store;
|
||||
|
||||
import cn.daxpay.open.platform.core.validation.ValidationGroup;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/// # 门店信息
|
||||
///
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "门店信息")
|
||||
public class MchStoreInfoParam {
|
||||
|
||||
/// 主键
|
||||
@Schema(description = "主键")
|
||||
@NotNull(message = "{validation.field.id.notNull}", groups = ValidationGroup.edit.class)
|
||||
private Long id;
|
||||
|
||||
/// 商户号
|
||||
@Schema(description = "商户号")
|
||||
private String mchNo;
|
||||
|
||||
/// 门店名称
|
||||
@Schema(description = "门店名称")
|
||||
@NotBlank(message = "{validation.field.storeName.notBlank}")
|
||||
private String storeName;
|
||||
|
||||
/// 联系人电话
|
||||
@Schema(description = "联系人电话")
|
||||
private String contactPhone;
|
||||
|
||||
/// 门店LOGO
|
||||
@Schema(description = "门店LOGO")
|
||||
private String logoUrl;
|
||||
|
||||
/// 门头照
|
||||
@Schema(description = "门头照")
|
||||
private String facadeUrl;
|
||||
|
||||
/// 门店内景照
|
||||
@Schema(description = "门店内景照")
|
||||
private String interiorUrl;
|
||||
|
||||
/// 行政区划代码
|
||||
@Schema(description = "行政区划代码")
|
||||
private String regionCode;
|
||||
|
||||
/// 详细地址
|
||||
@Schema(description = "详细地址")
|
||||
private String address;
|
||||
|
||||
/// 经度
|
||||
@Schema(description = "经度")
|
||||
private BigDecimal longitude;
|
||||
|
||||
/// 纬度
|
||||
@Schema(description = "纬度")
|
||||
private BigDecimal latitude;
|
||||
|
||||
/// 状态
|
||||
/// @see cn.daxpay.open.platform.core.enums.merchant.StoreStatusEnum
|
||||
@Schema(description = "状态")
|
||||
@NotBlank(message = "{validation.field.status.notBlank}")
|
||||
private String status;
|
||||
|
||||
/// 备注
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package cn.daxpay.open.payment.merchant.param.store;
|
||||
|
||||
import cn.daxpay.open.platform.core.annotation.QueryParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/// # 门店查询参数
|
||||
///
|
||||
@Data
|
||||
@QueryParam(type = QueryParam.CompareTypeEnum.LIKE)
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "门店查询参数")
|
||||
public class MchStoreInfoQuery {
|
||||
|
||||
/// 商户号
|
||||
@Schema(description = "商户号")
|
||||
@QueryParam(type = QueryParam.CompareTypeEnum.EQ)
|
||||
private String mchNo;
|
||||
|
||||
/// 门店号
|
||||
@Schema(description = "门店号")
|
||||
@QueryParam(type = QueryParam.CompareTypeEnum.EQ)
|
||||
private String storeNo;
|
||||
|
||||
/// 门店名称
|
||||
@Schema(description = "门店名称")
|
||||
private String storeName;
|
||||
|
||||
/// 联系人电话
|
||||
@Schema(description = "联系人电话")
|
||||
private String contactPhone;
|
||||
|
||||
/// 状态
|
||||
@Schema(description = "状态")
|
||||
@QueryParam(type = QueryParam.CompareTypeEnum.EQ)
|
||||
private String status;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package cn.daxpay.open.payment.merchant.result.store;
|
||||
|
||||
import cn.daxpay.open.platform.core.result.BaseResult;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import lombok.experimental.FieldNameConstants;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/// # 门店信息
|
||||
///
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@FieldNameConstants
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "门店信息")
|
||||
public class MchStoreInfoResult extends BaseResult {
|
||||
|
||||
@Schema(description = "商户号")
|
||||
private String mchNo;
|
||||
|
||||
@Schema(description = "门店号")
|
||||
private String storeNo;
|
||||
|
||||
@Schema(description = "门店名称")
|
||||
private String storeName;
|
||||
|
||||
@Schema(description = "联系人电话")
|
||||
private String contactPhone;
|
||||
|
||||
@Schema(description = "门店LOGO")
|
||||
private String logoUrl;
|
||||
|
||||
@Schema(description = "门头照")
|
||||
private String facadeUrl;
|
||||
|
||||
@Schema(description = "门店内景照")
|
||||
private String interiorUrl;
|
||||
|
||||
@Schema(description = "行政区划代码")
|
||||
private String regionCode;
|
||||
|
||||
@Schema(description = "详细地址")
|
||||
private String address;
|
||||
|
||||
@Schema(description = "经度")
|
||||
private BigDecimal longitude;
|
||||
|
||||
@Schema(description = "纬度")
|
||||
private BigDecimal latitude;
|
||||
|
||||
@Schema(description = "状态")
|
||||
private String status;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
package cn.daxpay.open.payment.merchant.service.store;
|
||||
|
||||
import cn.daxpay.open.payment.common.context.PaymentContext;
|
||||
import cn.daxpay.open.payment.merchant.convert.store.MchStoreInfoConvert;
|
||||
import cn.daxpay.open.payment.merchant.dao.info.MerchantInfoManager;
|
||||
import cn.daxpay.open.payment.merchant.dao.store.MchStoreInfoManager;
|
||||
import cn.daxpay.open.payment.merchant.entity.info.MerchantInfo;
|
||||
import cn.daxpay.open.payment.merchant.entity.store.MchStoreInfo;
|
||||
import cn.daxpay.open.payment.merchant.param.store.MchStoreInfoParam;
|
||||
import cn.daxpay.open.payment.merchant.param.store.MchStoreInfoQuery;
|
||||
import cn.daxpay.open.payment.merchant.result.store.MchStoreInfoResult;
|
||||
import cn.daxpay.open.platform.common.mybatisplus.util.MpUtil;
|
||||
import cn.daxpay.open.platform.core.code.CommonCode;
|
||||
import cn.daxpay.open.platform.core.enums.client.ClientEnum;
|
||||
import cn.daxpay.open.platform.core.exception.BizException;
|
||||
import cn.daxpay.open.platform.core.exception.BizInfoException;
|
||||
import cn.daxpay.open.platform.core.exception.DataNotExistException;
|
||||
import cn.daxpay.open.platform.core.exception.config.ConfigErrorException;
|
||||
import cn.daxpay.open.platform.core.rest.param.PageParam;
|
||||
import cn.daxpay.open.platform.core.rest.result.PageResult;
|
||||
import cn.daxpay.open.platform.iam.service.client.ClientCodeService;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/// # 门店信息管理
|
||||
///
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class MchStoreInfoService {
|
||||
|
||||
private final MchStoreInfoManager mchStoreInfoManager;
|
||||
|
||||
private final MerchantInfoManager merchantInfoManager;
|
||||
|
||||
private final ClientCodeService clientCodeService;
|
||||
|
||||
private final PaymentContext apiContext;
|
||||
|
||||
/// 新增门店
|
||||
public void add(MchStoreInfoParam param) {
|
||||
String mchNo = this.resolveMchNo(param.getMchNo());
|
||||
MerchantInfo merchant = merchantInfoManager.findByMchNo(mchNo)
|
||||
// 商户: 商户不存在
|
||||
.orElseThrow(() -> new BizException(CommonCode.FAIL_CODE, "error.payment.merchant.mchNotExist"));
|
||||
param.setMchNo(mchNo);
|
||||
MchStoreInfo entity = MchStoreInfoConvert.CONVERT.toEntity(param);
|
||||
// 生成门店号
|
||||
entity.setStoreNo(this.generateStoreNo());
|
||||
entity.setMchNo(mchNo);
|
||||
mchStoreInfoManager.save(entity);
|
||||
}
|
||||
|
||||
/// 修改门店
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void update(MchStoreInfoParam param) {
|
||||
MchStoreInfo mchStore = mchStoreInfoManager.findById(param.getId())
|
||||
// 商户: 门店不存在
|
||||
.orElseThrow(() -> new DataNotExistException("error.payment.merchant.storeNotFound"));
|
||||
this.checkStore(mchStore);
|
||||
MchStoreInfoConvert.CONVERT.copy(param, mchStore);
|
||||
mchStoreInfoManager.updateById(mchStore);
|
||||
}
|
||||
|
||||
/// 分页
|
||||
public PageResult<MchStoreInfoResult> page(PageParam pageParam, MchStoreInfoQuery query) {
|
||||
return MpUtil.toPageResult(mchStoreInfoManager.page(pageParam, query));
|
||||
}
|
||||
|
||||
/// 根据id查询
|
||||
public MchStoreInfoResult findById(Long id) {
|
||||
MchStoreInfo mchStore = mchStoreInfoManager.findById(id)
|
||||
// 商户: 门店不存在
|
||||
.orElseThrow(() -> new DataNotExistException("error.payment.merchant.storeNotFound"));
|
||||
this.checkStore(mchStore);
|
||||
return mchStore.toResult();
|
||||
}
|
||||
|
||||
/// 门店列表(商户端按当前商户过滤)
|
||||
public List<MchStoreInfoResult> list() {
|
||||
String mchNo = this.resolveMchNo(null);
|
||||
return mchStoreInfoManager.findAllByMchNo(mchNo).stream()
|
||||
.map(MchStoreInfo::toResult)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/// 删除
|
||||
public void delete(Long id) {
|
||||
MchStoreInfo mchStore = mchStoreInfoManager.findById(id)
|
||||
// 商户: 门店不存在
|
||||
.orElseThrow(() -> new DataNotExistException("error.payment.merchant.storeNotFound"));
|
||||
this.checkStore(mchStore);
|
||||
mchStoreInfoManager.deleteById(id);
|
||||
}
|
||||
|
||||
/// 生成门店号
|
||||
public String generateStoreNo() {
|
||||
String storeNo = "S" + RandomUtil.randomNumbers(16);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if (!mchStoreInfoManager.existsByStoreNo(storeNo)) {
|
||||
return storeNo;
|
||||
}
|
||||
storeNo = "S" + RandomUtil.randomNumbers(16);
|
||||
}
|
||||
// 商户: 门店号生成失败
|
||||
throw new BizException(CommonCode.FAIL_CODE, "error.payment.merchant.storeNoGenFailed");
|
||||
}
|
||||
|
||||
/// 解析商户号, 商户端从上下文获取, 管理端从参数获取
|
||||
private String resolveMchNo(String paramMchNo) {
|
||||
if (clientCodeService.getClientCode().equals(ClientEnum.MERCHANT.getCode())) {
|
||||
return apiContext.getTradeInfo().getMchNo();
|
||||
}
|
||||
if (paramMchNo == null) {
|
||||
// 商户: 数据错误,未发现商户号
|
||||
throw new BizInfoException(CommonCode.FAIL_CODE, "error.payment.merchant.dataErrorNoMchNo");
|
||||
}
|
||||
return paramMchNo;
|
||||
}
|
||||
|
||||
/// 如果和当前商户不匹配, 抛出错误(商户端校验)
|
||||
public void checkStore(MchStoreInfo mchStore) {
|
||||
if (clientCodeService.getClientCode().equals(ClientEnum.MERCHANT.getCode())) {
|
||||
if (!mchStore.getMchNo().equals(apiContext.getTradeInfo().getMchNo())) {
|
||||
// 商户: 门店不属于当前商户
|
||||
throw new ConfigErrorException("error.payment.merchant.storeNoMatch");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"disabled": "Disabled",
|
||||
"enable": "Enabled"
|
||||
}
|
||||
@@ -27,5 +27,6 @@
|
||||
"payRefundStatusNotExist": "Pay refund status not found: {0}",
|
||||
"payCallTypeNotSupported": "Unsupported checkout type: {0}",
|
||||
"channelAuthTypeNotExist": "Auth type not found: {0}",
|
||||
"mchAppStatusNotFound": "Merchant app status not found: {0}"
|
||||
"mchAppStatusNotFound": "Merchant app status not found: {0}",
|
||||
"storeStatusNotFound": "Store status not found: {0}"
|
||||
}
|
||||
|
||||
@@ -18,5 +18,8 @@
|
||||
"specifiedAppConfigNotFound": "Specified application configuration not found",
|
||||
"specifiedMchConfigNotFound": "Specified merchant configuration not found",
|
||||
"adminRoleNotExist": "Merchant admin role not found, please check",
|
||||
"apiConfigNotExist": "Merchant API configuration not found"
|
||||
"apiConfigNotExist": "Merchant API configuration not found",
|
||||
"storeNotFound": "Store not found",
|
||||
"storeNoGenFailed": "Store number generation failed",
|
||||
"storeNoMatch": "Store does not belong to the current merchant"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"disabled": "停用",
|
||||
"enable": "启用"
|
||||
}
|
||||
@@ -27,5 +27,6 @@
|
||||
"payRefundStatusNotExist": "该退款状态不存在: {0}",
|
||||
"payCallTypeNotSupported": "不支持的收银台类型: {0}",
|
||||
"channelAuthTypeNotExist": "认证类型不存在: {0}",
|
||||
"mchAppStatusNotFound": "未找到对应的商户应用状态类型: {0}"
|
||||
"mchAppStatusNotFound": "未找到对应的商户应用状态类型: {0}",
|
||||
"storeStatusNotFound": "未找到对应的门店状态类型: {0}"
|
||||
}
|
||||
|
||||
@@ -18,5 +18,8 @@
|
||||
"specifiedAppConfigNotFound": "未找到指定的应用配置",
|
||||
"specifiedMchConfigNotFound": "未找到指定的商户配置",
|
||||
"adminRoleNotExist": "商户管理员角色不存在, 请检查",
|
||||
"apiConfigNotExist": "商户API配置不存在"
|
||||
"apiConfigNotExist": "商户API配置不存在",
|
||||
"storeNotFound": "门店信息不存在",
|
||||
"storeNoGenFailed": "门店号生成失败",
|
||||
"storeNoMatch": "门店不属于当前商户"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package cn.daxpay.open.platform.core.enums.merchant;
|
||||
|
||||
import cn.daxpay.open.platform.core.exception.config.ConfigNotExistException;
|
||||
import cn.daxpay.open.platform.core.i18n.I18nSupport;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/// # 门店状态
|
||||
///
|
||||
/// 字典: store_status
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum StoreStatusEnum implements I18nSupport {
|
||||
|
||||
/// 禁用
|
||||
DISABLED("disabled"),
|
||||
/// 启用
|
||||
ENABLE("enable");
|
||||
|
||||
/// 编码
|
||||
private final String code;
|
||||
|
||||
/// 翻译 key 前缀
|
||||
@Override
|
||||
public String getI18nPrefix() {
|
||||
return "enum.store_status";
|
||||
}
|
||||
|
||||
/// 根据编码查找
|
||||
public static StoreStatusEnum findByCode(String code) {
|
||||
return Arrays.stream(values())
|
||||
.filter(e -> e.getCode().equals(code))
|
||||
.findFirst()
|
||||
// 通用: 未找到对应的门店状态类型: {0}
|
||||
.orElseThrow(() -> new ConfigNotExistException("error.common.storeStatusNotFound", code));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user