Commit 189cfd95 authored by wanghuazhou's avatar wanghuazhou

feat(500): 新货币汇率

parent d5879f0d
CREATE TABLE IF NOT EXISTS `ecw_currency_rate` (
`id` BIGINT AUTO_INCREMENT,
`source_id` BIGINT NOT NULL COMMENT '原币种',
`target_id` BIGINT NOT NULL COMMENT '支付币种',
`source_amount` DECIMAL(14, 4) NOT NULL COMMENT '原币种金额',
`target_amount` DECIMAL(14, 4) NOT NULL COMMENT '支付币种金额',
`countries` JSON NOT NULL COMMENT '国家',
`expiration` DATE NOT NULL COMMENT '有效日期',
`remarks` VARCHAR(255) NULL COMMENT '备注',
`creator` VARCHAR(32) NOT NULL COMMENT '创建者',
`create_time` DATETIME NOT NULL COMMENT '创建时间',
`updater` VARCHAR(32) NOT NULL COMMENT '更新者',
`update_time` DATETIME NOT NULL COMMENT '更新时间',
`deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (`id`)
) COMMENT '币种汇率表';
CREATE TABLE IF NOT EXISTS `ecw_currency_rate_log` (
`id` BIGINT AUTO_INCREMENT,
`rate_id` BIGINT NOT NULL COMMENT '汇率编号',
`source_amount1` DECIMAL(14, 4) NOT NULL COMMENT '修改前原币种金额',
`source_amount2` DECIMAL(14, 4) NOT NULL COMMENT '修改后原币种金额',
`target_amount1` DECIMAL(14, 4) NOT NULL COMMENT '修改前支付币种金额',
`target_amount2` DECIMAL(14, 4) NOT NULL COMMENT '修改后支付币种金额',
`expiration1` DATE NOT NULL COMMENT '修改前有效期',
`expiration2` DATE NOT NULL COMMENT '修改后有效期',
`remarks` VARCHAR(255) NULL COMMENT '备注',
`creator` VARCHAR(32) NOT NULL COMMENT '创建者',
`create_time` DATETIME NOT NULL COMMENT '创建时间',
`updater` VARCHAR(32) NOT NULL COMMENT '更新者',
`update_time` DATETIME NOT NULL COMMENT '更新时间',
`deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (`id`)
) COMMENT '币种汇率变更表';
\ No newline at end of file
......@@ -151,10 +151,13 @@ public interface ErrorCodeConstants {
ErrorCode CUSTOMER_CANNOT_DELAY_APPROVAL_WITH_NO_ENTER_OPEN_SEA_TIME = new ErrorCode(1004006028, "customer.cannot.delay.approval.with.no.enter.open.sea.time");
ErrorCode EXCHANGE_RATE_NOT_EXISTS = new ErrorCode(1004006029, "currency.rate.not.exists");
ErrorCode CURRENCY_RATE_NOT_EXISTS = new ErrorCode(1004006029, "currency.rate.not.exists");
ErrorCode EXCHANGE_RATE_LOG_NOT_EXISTS = new ErrorCode(1004006030, "汇率变更日志不存在");
ErrorCode EXCHANGE_RATE_EXISTS = new ErrorCode(1004006031, "currency.rate.exists");
ErrorCode CURRENCY_RATE_EXISTS = new ErrorCode(1004006031, "currency.rate.exists");
ErrorCode EXCHANGE_RATE_EXPIRE = new ErrorCode(1004006032, "currency.rate.disable");
ErrorCode CURRENCY_RATE_EXPIRED = new ErrorCode(1004006032, "currency.rate.disable");
ErrorCode EXCHANGE_RATE_NOT_EXISTS_PARAM = new ErrorCode(1004006033, "currency.rate.to.not.exists");
......@@ -191,6 +194,9 @@ public interface ErrorCodeConstants {
ErrorCode AREA_CODE_NOT_NULL = new ErrorCode(1004006044, "area.code.not.null");
ErrorCode CURRENCY_ID_NOT_NULL = new ErrorCode(1004006045, "currency.id.not.null");
ErrorCode CURRENCY_RATE_COUNTRIES_INVALID = new ErrorCode(1004006055, "currency.rate.countries.invalid");
ErrorCode CURRENCY_RATE_PAIR_INVALID = new ErrorCode(1004006056, "currency.rate.pair.invalid");
ErrorCode CURRENCY_RATE_AMOUNT_INVALID = new ErrorCode(1004006057, "currency.rate.amount.invalid");
ErrorCode CURRENCY_RATE_TOO_SMALL = new ErrorCode(1004006059, "currency.rate.too.small");
}
package cn.iocoder.yudao.module.ecw.controller.admin.currencyRate;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.ecw.dal.dataobject.currencyRate.CurrencyRateDO;
import cn.iocoder.yudao.module.ecw.dal.dataobject.currencyRate.CurrencyRateLogDO;
import cn.iocoder.yudao.module.ecw.service.currencyRate.CurrencyRateService;
import cn.iocoder.yudao.module.ecw.vo.currencyRate.CurrencyRateCreateReqVO;
import cn.iocoder.yudao.module.ecw.vo.currencyRate.CurrencyRateQueryParamVO;
import cn.iocoder.yudao.module.ecw.vo.currencyRate.CurrencyRateUpdateReqVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Validated
@RestController
@Api(tags = "管理后台 - 货币汇率")
@RequestMapping("/ecw/currency-rate")
public class CurrencyRateController {
@Autowired
private CurrencyRateService service;
@PostMapping("/create")
@ApiOperation("创建汇率信息")
public CommonResult<Boolean> create(@Valid @RequestBody CurrencyRateCreateReqVO req) {
service.create(req);
return success(true);
}
@PutMapping("/update")
@ApiOperation("更新汇率信息")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
public CommonResult<Boolean> update(@RequestParam("id") Long id, @Valid @RequestBody CurrencyRateUpdateReqVO req) {
service.update(id, req);
return success(true);
}
@DeleteMapping("/delete")
@ApiOperation("删除汇率信息")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
public CommonResult<Boolean> delete(@RequestParam("id") Long id) {
service.delete(id);
return success(true);
}
@GetMapping("/page")
@ApiOperation("分页查询汇率信息")
public CommonResult<PageResult<CurrencyRateDO>> page(@Valid CurrencyRateQueryParamVO param) {
return success(service.query(param));
}
@GetMapping("/get")
@ApiOperation("根据币种获取汇率信息")
public CommonResult<CurrencyRateDO> get(@RequestParam("sourceId") Long sourceId, @RequestParam("targetId") Long targetId) {
return success(service.find(sourceId, targetId));
}
@GetMapping("/logs")
@ApiOperation("根据币种获取汇率根据货币符号")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
public CommonResult<PageResult<CurrencyRateLogDO>> logs(@RequestParam("id") Long id, PageParam page) {
return success(service.history(id, page));
}
}
package cn.iocoder.yudao.module.ecw.convert.currencyRate;
import cn.iocoder.yudao.module.ecw.dal.dataobject.currencyRate.CurrencyRateDO;
import cn.iocoder.yudao.module.ecw.vo.currencyRate.CurrencyRateCreateReqVO;
import cn.iocoder.yudao.module.ecw.vo.currencyRate.CurrencyRateUpdateReqVO;
import org.mapstruct.Mapper;
import org.mapstruct.MappingTarget;
import org.mapstruct.factory.Mappers;
@Mapper
public interface CurrencyRateConvert {
CurrencyRateConvert INSTANCE = Mappers.getMapper(CurrencyRateConvert.class);
CurrencyRateDO from(CurrencyRateCreateReqVO req);
void update(@MappingTarget CurrencyRateDO saved, CurrencyRateUpdateReqVO req);
}
package cn.iocoder.yudao.module.ecw.dal.dataobject.currencyRate;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Set;
/**
* 货币汇率 DO
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName("ecw_currency_rate")
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CurrencyRateDO extends BaseDO {
/**
*
*/
@TableId
private Long id;
/**
* 原币种
*/
private Long sourceId;
/**
* 支付币种
*/
private Long targetId;
/**
* 原币种金额
*/
private BigDecimal sourceAmount;
/**
* 支付币种金额
*/
private BigDecimal targetAmount;
/**
* 汇率值
*/
private BigDecimal rate;
/**
* 国家
*/
@TableField(typeHandler = JsonLongSetTypeHandler.class)
private Set<Long> countries;
/**
* 有效期
*/
private LocalDate expiration;
/**
* 备注
*/
private String remarks;
}
package cn.iocoder.yudao.module.ecw.dal.dataobject.currencyRate;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.math.BigDecimal;
import java.time.LocalDate;
/**
* 货币汇率变更历史 DO
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName("ecw_currency_rate_log")
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CurrencyRateLogDO extends BaseDO {
/**
*
*/
@TableId
private Long id;
/**
* 汇率编号
*/
private Long rateId;
/**
* 原币种变更前金额
*/
private BigDecimal sourceAmount1;
/**
* 原币种变更后金额
*/
private BigDecimal sourceAmount2;
/**
* 支付币种变更前金额
*/
private BigDecimal targetAmount1;
/**
* 支付币种变更后金额
*/
private BigDecimal targetAmount2;
/**
* 有效期
*/
private LocalDate expiration1;
/**
* 有效期
*/
private LocalDate expiration2;
/**
* 备注
*/
private String remarks;
}
package cn.iocoder.yudao.module.ecw.dal.mysql.currencyRate;
import cn.iocoder.yudao.framework.mybatis.core.mapper.AbstractMapper;
import cn.iocoder.yudao.module.ecw.dal.dataobject.currencyRate.CurrencyRateLogDO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface CurrencyRateLogMapper extends AbstractMapper<CurrencyRateLogDO> {
}
package cn.iocoder.yudao.module.ecw.dal.mysql.currencyRate;
import cn.iocoder.yudao.framework.mybatis.core.mapper.AbstractMapper;
import cn.iocoder.yudao.module.ecw.dal.dataobject.currencyRate.CurrencyRateDO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface CurrencyRateMapper extends AbstractMapper<CurrencyRateDO> {
}
package cn.iocoder.yudao.module.ecw.service.currencyRate;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.ecw.dal.dataobject.currencyRate.CurrencyRateDO;
import cn.iocoder.yudao.module.ecw.dal.dataobject.currencyRate.CurrencyRateLogDO;
import cn.iocoder.yudao.module.ecw.vo.currencyRate.CurrencyRateCreateReqVO;
import cn.iocoder.yudao.module.ecw.vo.currencyRate.CurrencyRateQueryParamVO;
import cn.iocoder.yudao.module.ecw.vo.currencyRate.CurrencyRateUpdateReqVO;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.Optional;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.ecw.enums.ErrorCodeConstants.CURRENCY_RATE_AMOUNT_INVALID;
import static cn.iocoder.yudao.module.ecw.enums.ErrorCodeConstants.CURRENCY_RATE_EXPIRED;
import static cn.iocoder.yudao.module.ecw.enums.ErrorCodeConstants.CURRENCY_RATE_NOT_EXISTS;
import static cn.iocoder.yudao.module.ecw.enums.ErrorCodeConstants.CURRENCY_RATE_TOO_SMALL;
/**
* 货币汇率服务
*/
public interface CurrencyRateService {
/**
* 汇率精度。
*/
int RATE_SCALE = 8;
/**
* 汇率四舍五入。
*/
RoundingMode RATE_ROUNDING = RoundingMode.HALF_UP;
/**
* 计算两个金额的汇率。
*
* @param source 原金额
* @param target 目标金额
* @return 汇率
* @throws ServiceException 金额小于或等零,或者汇率小于精度下最小值
*/
default BigDecimal rate(BigDecimal source, BigDecimal target) throws ServiceException {
if (source.compareTo(BigDecimal.ZERO) <= 0 || target.compareTo(BigDecimal.ZERO) <= 0) {
throw exception(CURRENCY_RATE_AMOUNT_INVALID);
}
return Optional.of(target.divide(source, RATE_SCALE, RATE_ROUNDING))
.filter(it -> it.compareTo(BigDecimal.ZERO) > 0)
.orElseThrow(() -> exception(CURRENCY_RATE_TOO_SMALL));
}
/**
* 计算两个币种的汇率。
*
* @param sourceId 原币种编号
* @param targetId 支付币种编号
* @return 汇率比值,为空则表示汇率不存在
* @throws ServiceException 汇率不存在或过期
*/
default BigDecimal rate(long sourceId, long targetId) throws ServiceException {
CurrencyRateDO entity = Optional.ofNullable(find(sourceId, targetId))
.orElseThrow(() -> exception(CURRENCY_RATE_NOT_EXISTS));
LocalDate now = LocalDate.now();
if (now.isAfter(entity.getExpiration())) {
throw exception(CURRENCY_RATE_EXPIRED);
}
return rate(entity.getSourceAmount(), entity.getTargetAmount());
}
/**
* 计算两个币种的汇率。
*
* @param sourceId 原币种编号
* @param targetId 支付币种编号
* @param tryOpposite 如果不存在则使用反向汇率计算
* @return 汇率比值,为空则表示汇率不存在
* @throws ServiceException 汇率不存在或过期或反向汇率过小
*/
default BigDecimal rate(long sourceId, long targetId, boolean tryOpposite) throws ServiceException {
try {
return rate(sourceId, targetId);
} catch (ServiceException e) {
if (!tryOpposite) {
throw e;
}
return BigDecimal.ONE.divide(rate(targetId, sourceId), RATE_SCALE, RATE_ROUNDING);
}
}
/**
* 创建新汇率。
*
* @param req 创建请求
* @throws ServiceException 汇率已存在或金额国家等参数不合法
*/
void create(CurrencyRateCreateReqVO req);
/**
* 获取汇率信息。
*
* @param sourceId 原币种编号
* @param targetId 支付币种编号
* @return 汇率信息,可能为空
*/
CurrencyRateDO find(long sourceId, long targetId);
/**
* 分页查询汇率。
*
* @param param 分页参数
* @return 分页结果
*/
PageResult<CurrencyRateDO> query(CurrencyRateQueryParamVO param);
/**
* 更新汇率信息。
*
* @param id 汇率信息编号
* @param req 更新请求
* @throws ServiceException 汇率不存在或金额等参数不合法
*/
void update(long id, CurrencyRateUpdateReqVO req);
/**
* 删除汇率信息。
*
* @param id 汇率信息编号
*/
void delete(long id);
/**
* 分页查询汇率变更历史。
*
* @param id 汇率信息编号
* @param param 分页参数
* @return 分页结果
*/
PageResult<CurrencyRateLogDO> history(long id, PageParam param);
}
package cn.iocoder.yudao.module.ecw.service.currencyRate;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.ecw.convert.currencyRate.CurrencyRateConvert;
import cn.iocoder.yudao.module.ecw.dal.dataobject.currencyRate.CurrencyRateDO;
import cn.iocoder.yudao.module.ecw.dal.dataobject.currencyRate.CurrencyRateLogDO;
import cn.iocoder.yudao.module.ecw.dal.mysql.currencyRate.CurrencyRateLogMapper;
import cn.iocoder.yudao.module.ecw.dal.mysql.currencyRate.CurrencyRateMapper;
import cn.iocoder.yudao.module.ecw.service.country.CountryService;
import cn.iocoder.yudao.module.ecw.service.currency.CurrencyService;
import cn.iocoder.yudao.module.ecw.vo.currencyRate.CurrencyRateCreateReqVO;
import cn.iocoder.yudao.module.ecw.vo.currencyRate.CurrencyRateQueryParamVO;
import cn.iocoder.yudao.module.ecw.vo.currencyRate.CurrencyRateUpdateReqVO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.Optional;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.ecw.enums.ErrorCodeConstants.CURRENCY_NOT_EXISTS;
import static cn.iocoder.yudao.module.ecw.enums.ErrorCodeConstants.CURRENCY_RATE_COUNTRIES_INVALID;
import static cn.iocoder.yudao.module.ecw.enums.ErrorCodeConstants.CURRENCY_RATE_EXISTS;
import static cn.iocoder.yudao.module.ecw.enums.ErrorCodeConstants.CURRENCY_RATE_NOT_EXISTS;
import static cn.iocoder.yudao.module.ecw.enums.ErrorCodeConstants.CURRENCY_RATE_PAIR_INVALID;
@Service
public class CurrencyRateServiceImpl implements CurrencyRateService {
@Autowired
private CountryService countryService;
@Autowired
private CurrencyService currencyService;
@Autowired
private CurrencyRateMapper mapper;
@Autowired
private CurrencyRateLogMapper logMapper;
// 检查指定币种是否存在
private void currency(long id) {
Optional.ofNullable(currencyService.getCurrency((int) id))
.orElseThrow(() -> exception(CURRENCY_NOT_EXISTS));
}
@Override
public void create(CurrencyRateCreateReqVO req) {
long sourceId = req.getSourceId();
long targetId = req.getTargetId();
Set<Long> countries = req.getCountries();
if (sourceId == targetId) {
throw exception(CURRENCY_RATE_PAIR_INVALID);
}
rate(req.getSourceAmount(), req.getTargetAmount()); // check rate
if (countries.isEmpty() || (countries.size() != countryService.getCountryList(countries).size())) {
throw exception(CURRENCY_RATE_COUNTRIES_INVALID);
}
// check if currencies exist
currency(sourceId);
currency(targetId);
if (find(sourceId, targetId) != null) {
throw exception(CURRENCY_RATE_EXISTS);
}
mapper.insert(CurrencyRateConvert.INSTANCE.from(req));
}
@Override
public CurrencyRateDO find(long sourceId, long targetId) {
LambdaQueryWrapper<CurrencyRateDO> wrapper = Wrappers.lambdaQuery(CurrencyRateDO.class)
.eq(CurrencyRateDO::getSourceId, sourceId)
.eq(CurrencyRateDO::getTargetId, targetId);
return mapper.selectOne(wrapper);
}
@Override
public PageResult<CurrencyRateDO> query(CurrencyRateQueryParamVO param) {
LocalDate now = LocalDate.now();
LambdaQueryWrapper<CurrencyRateDO> wrapper = Wrappers.lambdaQuery(CurrencyRateDO.class)
.eq(param.getSourceId() != null, CurrencyRateDO::getSourceId, param.getSourceId())
.eq(param.getTargetId() != null, CurrencyRateDO::getTargetId, param.getTargetId())
// TODO countries intersect
.gt(param.getExpired() == Boolean.FALSE, CurrencyRateDO::getExpiration, now)
.lt(param.getExpired() == Boolean.TRUE, CurrencyRateDO::getExpiration, now)
.gt(param.getExpirationAfter() != null, CurrencyRateDO::getExpiration, param.getExpirationAfter())
.lt(param.getExpirationBefore() != null, CurrencyRateDO::getExpiration, param.getExpirationBefore())
.orderByDesc(Arrays.asList(CurrencyRateDO::getUpdateTime, CurrencyRateDO::getExpiration));
return mapper.selectPage(param, wrapper);
}
@Override
public void update(long id, CurrencyRateUpdateReqVO req) {
rate(req.getSourceAmount(), req.getTargetAmount()); // check rate
CurrencyRateLogDO change = new CurrencyRateLogDO();
CurrencyRateDO saved = Optional.ofNullable(mapper.selectById(id))
.orElseThrow(() -> exception(CURRENCY_RATE_NOT_EXISTS));
// 修改前
change.setSourceAmount1(saved.getSourceAmount());
change.setTargetAmount1(saved.getTargetAmount());
change.setExpiration1(saved.getExpiration());
// 修改后
change.setSourceAmount2(req.getSourceAmount());
change.setTargetAmount2(req.getTargetAmount());
change.setExpiration2(req.getExpiration());
change.setRateId(id);
change.setRemarks(req.getRemarks());
logMapper.insert(change);
CurrencyRateConvert.INSTANCE.update(saved, req);
mapper.updateById(saved);
}
@Override
public void delete(long id) {
mapper.deleteById(id);
}
@Override
public PageResult<CurrencyRateLogDO> history(long id, PageParam param) {
LambdaQueryWrapper<CurrencyRateLogDO> wrapper = Wrappers.lambdaQuery(CurrencyRateLogDO.class)
.eq(CurrencyRateLogDO::getRateId, id)
.orderByDesc(CurrencyRateLogDO::getCreateTime);
return logMapper.selectPage(param, wrapper);
}
}
package cn.iocoder.yudao.module.ecw.vo.currencyRate;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
@Data
@ApiModel("管理后台 - 货币汇率创建 Request VO")
public class CurrencyRateCreateReqVO {
@ApiModelProperty(value = "原币种", required = true)
@NotNull(message = "原币种不能为空")
private Long sourceId;
@ApiModelProperty(value = "支付币种", required = true)
@NotNull(message = "支付币种不能为空")
private Long targetId;
@ApiModelProperty(value = "原币种金额", required = true)
@NotNull(message = "原币种不能为空")
@Min(0)
private BigDecimal sourceAmount;
@ApiModelProperty(value = "支付币种", required = true)
@NotNull(message = "支付币种不能为空")
@Min(0)
private BigDecimal targetAmount;
@ApiModelProperty(value = "国家", required = true)
@NotNull(message = "至少选择一个国家")
private Set<Long> countries;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
@ApiModelProperty(value = "汇率有效截止日期")
private LocalDate expiration;
@ApiModelProperty(value = "备注")
private String remarks;
}
package cn.iocoder.yudao.module.ecw.vo.currencyRate;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDate;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
@Data
@ApiModel("管理后台 - 货币汇率查询 VO")
public class CurrencyRateQueryParamVO extends PageParam {
@ApiModelProperty(value = "原币种")
private Long sourceId;
@ApiModelProperty(value = "支付币种")
private Long targetId;
@ApiModelProperty(value = "国家")
private Set<Long> countries;
@ApiModelProperty(value = "状态")
private Boolean expired;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
@ApiModelProperty(value = "有效期大于")
private LocalDate expirationAfter;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
@ApiModelProperty(value = "有效期小于")
private LocalDate expirationBefore;
}
package cn.iocoder.yudao.module.ecw.vo.currencyRate;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.time.LocalDate;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
@Data
@ApiModel("管理后台 - 货币汇率更新 Request VO")
public class CurrencyRateUpdateReqVO {
@ApiModelProperty(value = "原币种金额", required = true)
@NotNull(message = "原币种不能为空")
@Min(0)
private BigDecimal sourceAmount;
@ApiModelProperty(value = "支付币种", required = true)
@NotNull(message = "支付币种不能为空")
@Min(0)
private BigDecimal targetAmount;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
@ApiModelProperty(value = "汇率有效截止日期")
private LocalDate expiration;
@ApiModelProperty(value = "备注")
private String remarks;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment