货币汇率转换策略

货币汇率转换表结构

CREATE TABLE `currency_symbol` (
  `currency_code` CHAR(5) NOT NULL COMMENT '货币代码',
  `currency_symbol` CHAR(5) NOT NULL COMMENT '货币符号',
  `from` DECIMAL(10,5) NOT NULL COMMENT '英镑转其他货币汇率',
  `to` DECIMAL(10,5) NOT NULL COMMENT '其他货币转英镑汇率',
  PRIMARY KEY (`currency_code`),
  UNIQUE INDEX `currency_UNIQUE` (`currency_code` ASC));

货币汇率转换数据

INSERT INTO `currency_symbol` (`currency_code`, `currency_symbol`, `from`, `to`) VALUES ('GBP', '£', '1', '1');
INSERT INTO `currency_symbol` (`currency_code`, `currency_symbol`, `from`, `to`) VALUES ('RMB', '¥', '8.7364', '6.7801');

请求头参数管理器

package com.das.security;

import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;

/**
 * liangmy
 * 请求头参数管理器
 *
 * @date 2020/08/08
 */
public class HeaderContextHolder {
    public static String Timezone = "Timezone";
    public static String CurrencyCode = "CurrencyCode";
    // 时区
    private static ThreadLocal<String> timezoneHolder = new ThreadLocal<>();
    // 货币代码
    private static ThreadLocal<String> currencyCodeHolder = new ThreadLocal<>();

    public static void holderHeader(HttpServletRequest request) {
        String timezone = request.getHeader(HeaderContextHolder.Timezone);
        timezone = StringUtils.isBlank(timezone) ? "+0" : timezone;
        timezoneHolder.set(timezone);
        String currencySymbol = request.getHeader(HeaderContextHolder.CurrencyCode);
        currencySymbol = StringUtils.isBlank(currencySymbol) ? "GBP" : currencySymbol;
        currencyCodeHolder.set(currencySymbol);
    }

    // 获取当前请求时区
    public static String getTimezone() {
        return timezoneHolder.get();
    }

    // 获取当前请求货币代码
    public static String getCurrencyCode() {
        return currencyCodeHolder.get();
    }

}
  • HTTP请求Header中增加扩展参数CurrencyCode(货币代码)
  • 后端通过Filter获取CurrencyCode参数,保存在当前请求中。
  • CurrencyCode默认值为GBP(英国货币代码)

货币汇率管理器

package com.das.security;

import com.das.entity.system.CurrencySymbolEntity;
import com.das.service.system.CurrencySymbolService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author liangmy
 * 货币汇率管理器
 * @Date 2020/09/22
 */
@Slf4j
@Component
public class CurrencySymbolHelper implements ApplicationListener<ContextRefreshedEvent> {

    private static ConcurrentHashMap<String, CurrencySymbolEntity> CurrencySymbolMap = new ConcurrentHashMap<>();


    // 当前系统货币汇率转换信息
    public static List<CurrencySymbolEntity> getCurrencySymbolEntityList() {
        return Collections.unmodifiableList(new ArrayList<>(CurrencySymbolMap.values()));
    }

    // 获取当前请求货币代码
    public static String getCurrencyCode() {
        return HeaderContextHolder.getCurrencyCode();
    }

    // 获取当前请求货币信息
    public static CurrencySymbolEntity getCurrencySymbolEntity() {
        CurrencySymbolEntity currencySymbolEntity = CurrencySymbolMap.get(getCurrencyCode());
        return currencySymbolEntity;
    }

    // 获取当前请求货币符号
    public static String getCurrencySymbol() {
        CurrencySymbolEntity currencySymbolEntity = getCurrencySymbolEntity();
        if (null != currencySymbolEntity) {
            return currencySymbolEntity.getCurrencySymbol();
        }
        return "";
    }


    @Autowired
    private CurrencySymbolService currencySymbolService;


    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        log.info("容器启动完成,加载货币信息");
        List<CurrencySymbolEntity> currencySymbolEntityList = currencySymbolService.getCurrencySymbolEntityList();
        for (CurrencySymbolEntity currencySymbolEntity : currencySymbolEntityList) {
            CurrencySymbolMap.put(currencySymbolEntity.getCurrencyCode(), currencySymbolEntity);
        }

    }
}
  • 实现ApplicationListener监听器,监听ContextRefreshedEvent事件发布。
  • ContextRefreshedEvent事件发布时加载货币汇率信息到内存中。

 

货币汇率转换函数(LittleBear)

    /**
     * 英镑转其他货币
     * 用于AOP:根据ob对象内域上标注的@CurrencySymbolTrans注解或response数组指定的域,通过reflect修改对应域汇率转换之后的值
     *
     * @param ob       需要货币汇率转换的对象
     * @param response 用于项目外对象,无法添加@CurrencySymbolTrans注解的对象。
     * @return :
     */
    public void currencySymbolTransformForClass(Object ob, String[] response) throws IllegalAccessException, NoSuchFieldException, IntrospectionException, InvocationTargetException {
        if (null == ob) {
            return;
        }
        if (Number.class.isAssignableFrom(ob.getClass())) {
            // 基础数据类型 - 数字类型
            Field declaredField = ob.getClass().getDeclaredField("value");
            declaredField.setAccessible(true);

            if (Double.class.isAssignableFrom(ob.getClass())) {
                Double argReturn = currencySymbolTransformReturn((Double) ob);
                declaredField.set(ob, argReturn);
            } else if (Float.class.isAssignableFrom(ob.getClass())) {
                Float argReturn = currencySymbolTransformReturn((Float) ob);
                declaredField.set(ob, argReturn);
            } else if (Long.class.isAssignableFrom(ob.getClass())) {
                Long argReturn = currencySymbolTransformReturn((Long) ob);
                declaredField.set(ob, argReturn);
            } else if (Integer.class.isAssignableFrom(ob.getClass())) {
                Integer argReturn = currencySymbolTransformReturn((Integer) ob);
                declaredField.set(ob, argReturn);
            } else if (Short.class.isAssignableFrom(ob.getClass())) {
                Short argReturn = currencySymbolTransformReturn((Short) ob);
                declaredField.set(ob, argReturn);
            } else if (Byte.class.isAssignableFrom(ob.getClass())) {
                Byte argReturn = currencySymbolTransformReturn((Byte) ob);
                declaredField.set(ob, argReturn);
            }
        } else if (String.class.isAssignableFrom(ob.getClass())) {
            // 基础数据类型 - 字符串

        } else if (Collection.class.isAssignableFrom(ob.getClass())) {
            // 集合类型 - 单值集合对象
            List fieldValue = (List) ob;
            for (Object fieldValueOb : fieldValue) {
                currencySymbolTransformForClass(fieldValueOb, response);
            }
        } else if (Map.class.isAssignableFrom(ob.getClass())) {
            // 集合类型 - key - value
            Map fieldValue = (Map) ob;
            for (Object entry : fieldValue.entrySet()) {
                Map.Entry<Object, Object> mapEntry = (Map.Entry<Object, Object>) entry;
                currencySymbolTransformForClass(mapEntry.getValue(), response);
            }
        } else {
            // 复合类型 - 非集合、非基础数据
            Field[] fields = ob.getClass().getDeclaredFields();
            for (Field field : fields) {
                if (Modifier.isStatic(field.getModifiers())) {
                    continue;
                }
                CurrencySymbolTrans annotation = field.getAnnotation(CurrencySymbolTrans.class);
                if (null == annotation) {
                    // 方法注解指定域名称
                    // 主要用于项目外对象,无法添加@CurrencySymbolTrans注解的对象。
                    if (!Arrays.asList(response).contains(field.getName())) {
                        continue;
                    }
                }
                field.setAccessible(true);
                if (Number.class.isAssignableFrom(field.getType())) {
                    currencySymbolTransformForClass(field.get(ob), response);
                } else if (String.class.isAssignableFrom(field.getType())) {
                    String obField = (String) field.get(ob);
                    PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), ob.getClass());
                    Method writeMethod = propertyDescriptor.getWriteMethod();
                    String argReturn = String.valueOf(currencySymbolTransformReturn(Double.valueOf((String) obField)));
                    writeMethod.invoke(ob, argReturn);
                } else if (Collection.class.isAssignableFrom(field.getType())) {
                    if (List.class.isAssignableFrom(field.getType())) {
                        currencySymbolTransformForClass(field.get(ob), response);
                    }
                } else if (field.getType().isArray()) {

                } else if (field.getType().isEnum()) {

                } else {
                    // Object
                    currencySymbolTransformForClass(field.get(ob), response);
                }
            }
        }
    }


    /**
     * 汇率转换
     * @param money     被转换金额
     * @return      转换之后的金额
     */
    public Double currencySymbolTransformReturn(Double money) {
        if (null != money) {
            String currencySymbolTransform = currencySymbolTransform(BigDecimal.valueOf(money), null);
            return Double.valueOf(currencySymbolTransform);
        }
        return money;
    }

    /**
     * 汇率转换
     * @param money     被转换金额
     * @return      转换之后的金额
     */
    public Float currencySymbolTransformReturn(Float money) {
        if (null != money) {
            String currencySymbolTransform = currencySymbolTransform(BigDecimal.valueOf(money), null);
            return Float.valueOf(currencySymbolTransform);
        }
        return money;
    }

    /**
     * 汇率转换
     * @param money     被转换金额
     * @return      转换之后的金额
     */
    public Long currencySymbolTransformReturn(Long money) {
        if (null != money) {
            String currencySymbolTransform = currencySymbolTransform(BigDecimal.valueOf(money), null);
            return Long.valueOf(currencySymbolTransform);
        }
        return money;
    }

    /**
     * 汇率转换
     * @param money     被转换金额
     * @return      转换之后的金额
     */
    public Integer currencySymbolTransformReturn(Integer money) {
        if (null != money) {
            String currencySymbolTransform = currencySymbolTransform(BigDecimal.valueOf(money), null);
            return Integer.valueOf(currencySymbolTransform);
        }
        return money;
    }

    /**
     * 汇率转换
     * @param money     被转换金额
     * @return      转换之后的金额
     */
    public Short currencySymbolTransformReturn(Short money) {
        if (null != money) {
            String currencySymbolTransform = currencySymbolTransform(BigDecimal.valueOf(money), null);
            return Short.valueOf(currencySymbolTransform);
        }
        return money;
    }

    /**
     * 汇率转换
     * @param money     被转换金额
     * @return      转换之后的金额
     */
    public Byte currencySymbolTransformReturn(Byte money) {
        if (null != money) {
            String currencySymbolTransform = currencySymbolTransform(BigDecimal.valueOf(money), null);
            return Byte.valueOf(currencySymbolTransform);
        }
        return money;
    }

    /**
     * 汇率转换
     * @param money 被转换金额
     * @param before 货币符号位置(true:在金额前;false:在金额后)
     * @return 带货币符号的金额
     */
    public String currencySymbolTransform(BigDecimal money, Boolean before) {
        CurrencySymbolEntity currencySymbolEntity = CurrencySymbolHelper.getCurrencySymbolEntity();
        if (null != currencySymbolEntity) {
            double v = money.multiply(BigDecimal.valueOf(currencySymbolEntity.getFrom())).setScale(EtcConstant.SCALE_TWO, RoundingMode.HALF_UP).doubleValue();

            String currencySymbol = currencySymbolEntity.getCurrencySymbol();

            if (null == before) {
                return String.format("%.2f", v);
            } else if (before) {
                return String.format("%s%.2f", currencySymbol, v);
            } else {
                return String.format("%.2f%s", v, currencySymbol);
            }

        }
        return String.format("%.2f", money.setScale(EtcConstant.SCALE_TWO, RoundingMode.HALF_UP).doubleValue());
    }

    /**
     * 英镑转其他货币
     * 用于AOP:根据arg对象内域上标注的@CurrencySymbolTrans注解,通过reflect修改对应域汇率转换之后的值
     * @param arg    需要货币汇率转换的对象
     * @return :
     */
    public void currencySymbolTranstoForClass(Object arg) throws IllegalAccessException, NoSuchFieldException {
        if (null == arg) {
            return;
        }
        if (Number.class.isAssignableFrom(arg.getClass())) {
            // 基础数据类型 - 数字类型
            Field declaredField = arg.getClass().getDeclaredField("value");
            declaredField.setAccessible(true);

            if (Double.class.isAssignableFrom(arg.getClass())) {
                Double argReturn = currencySymbolTranstoReturn((Double) arg);
                declaredField.set(arg, argReturn);
            } else if (Float.class.isAssignableFrom(arg.getClass())) {
                Float argReturn = currencySymbolTranstoReturn((Float) arg);
                declaredField.set(arg, argReturn);
            } else if (Long.class.isAssignableFrom(arg.getClass())) {
                Long argReturn = currencySymbolTranstoReturn((Long) arg);
                declaredField.set(arg, argReturn);
            } else if (Integer.class.isAssignableFrom(arg.getClass())) {
                Integer argReturn = currencySymbolTranstoReturn((Integer) arg);
                declaredField.set(arg, argReturn);
            } else if (Short.class.isAssignableFrom(arg.getClass())) {
                Short argReturn = currencySymbolTranstoReturn((Short) arg);
                declaredField.set(arg, argReturn);
            } else if (Byte.class.isAssignableFrom(arg.getClass())) {
                Byte argReturn = currencySymbolTranstoReturn((Byte) arg);
                declaredField.set(arg, argReturn);
            }
        } else if (String.class.isAssignableFrom(arg.getClass())) {
            // 基础数据类型 - 字符串类型
        } else if (Collection.class.isAssignableFrom(arg.getClass())) {
            // 集合数据类型 - 单值集合对象
            List fieldValue = (List) arg;
            for (Object fieldValueOb : fieldValue) {
                currencySymbolTranstoForClass(fieldValueOb);
            }
        } else {
            // 复合数据类型 - 非集合、非基础数据
            Field[] fields = arg.getClass().getDeclaredFields();
            for (Field field : fields) {
                if (Modifier.isStatic(field.getModifiers())) {
                    continue;
                }
                CurrencySymbolTrans annotation = field.getAnnotation(CurrencySymbolTrans.class);
                if (null == annotation) {
                    continue;
                }
                field.setAccessible(true);
                if (Number.class.isAssignableFrom(field.getType())) {
                    currencySymbolTranstoForClass(field.get(arg));
                } else if (String.class.isAssignableFrom(field.getType())) {
                    currencySymbolTranstoForClass(field.get(arg));
                } else if (Collection.class.isAssignableFrom(field.getType())) {
                    if (List.class.isAssignableFrom(field.getType())) {
                        currencySymbolTranstoForClass((List) field.get(arg));
                    }
                } else if (field.getType().isArray()) {

                } else if (field.getType().isEnum()) {

                } else {
                    // Object
                    currencySymbolTranstoForClass(field.get(arg));
                }
            }
        }
    }

    /**
     * 汇率转换
     * @param money 被转换的金额
     * @return 转换之后的金额
     */
    public Byte currencySymbolTranstoReturn(Byte money) {
        if (null != money) {
            CurrencySymbolEntity currencySymbolEntity = CurrencySymbolHelper.getCurrencySymbolEntity();
            if (null != currencySymbolEntity) {
                return BigDecimal.valueOf(money).multiply(BigDecimal.valueOf(currencySymbolEntity.getTo())).setScale(EtcConstant.SCALE_TWO, RoundingMode.HALF_UP).byteValue();
            }
        }
        return money;
    }

    /**
     * 汇率转换
     * @param money 被转换的金额
     * @return 转换之后的金额
     */
    public Short currencySymbolTranstoReturn(Short money) {
        if (null != money) {
            CurrencySymbolEntity currencySymbolEntity = CurrencySymbolHelper.getCurrencySymbolEntity();
            if (null != currencySymbolEntity) {
                return BigDecimal.valueOf(money).multiply(BigDecimal.valueOf(currencySymbolEntity.getTo())).setScale(EtcConstant.SCALE_TWO, RoundingMode.HALF_UP).shortValue();
            }
        }
        return money;
    }

    /**
     * 汇率转换
     * @param money 被转换的金额
     * @return 转换之后的金额
     */
    public Integer currencySymbolTranstoReturn(Integer money) {
        if (null != money) {
            CurrencySymbolEntity currencySymbolEntity = CurrencySymbolHelper.getCurrencySymbolEntity();
            if (null != currencySymbolEntity) {
                return BigDecimal.valueOf(money).multiply(BigDecimal.valueOf(currencySymbolEntity.getTo())).setScale(EtcConstant.SCALE_TWO, RoundingMode.HALF_UP).intValue();
            }
        }
        return money;
    }

    /**
     * 汇率转换
     * @param money 被转换的金额
     * @return 转换之后的金额
     */
    public Long currencySymbolTranstoReturn(Long money) {
        if (null != money) {
            CurrencySymbolEntity currencySymbolEntity = CurrencySymbolHelper.getCurrencySymbolEntity();
            if (null != currencySymbolEntity) {
                return BigDecimal.valueOf(money).multiply(BigDecimal.valueOf(currencySymbolEntity.getTo())).setScale(EtcConstant.SCALE_TWO, RoundingMode.HALF_UP).longValue();
            }
        }
        return money;
    }

    /**
     * 汇率转换
     * @param money 被转换的金额
     * @return 转换之后的金额
     */
    public Float currencySymbolTranstoReturn(Float money) {
        if (null != money) {
            CurrencySymbolEntity currencySymbolEntity = CurrencySymbolHelper.getCurrencySymbolEntity();
            if (null != currencySymbolEntity) {
                return BigDecimal.valueOf(money).multiply(BigDecimal.valueOf(currencySymbolEntity.getTo())).setScale(EtcConstant.SCALE_TWO, RoundingMode.HALF_UP).floatValue();
            }
        }
        return money;
    }

    /**
     * 汇率转换
     * @param money 被转换的金额
     * @return 转换之后的金额
     */
    public Double currencySymbolTranstoReturn(Double money) {
        if (null != money) {
            CurrencySymbolEntity currencySymbolEntity = CurrencySymbolHelper.getCurrencySymbolEntity();
            if (null != currencySymbolEntity) {
                return BigDecimal.valueOf(money).multiply(BigDecimal.valueOf(currencySymbolEntity.getTo())).setScale(EtcConstant.SCALE_TWO, RoundingMode.HALF_UP).doubleValue();
            }
        }
        return money;
    }

AOP

AOP注解

package com.das.aop;


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


/**
 * @Author : liangmy
 * @Description : 标识需要转换的域或对象
 * @Date : Created in 2020/09/25
 * @Modified By :
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
public @interface CurrencySymbolTrans {

    /**
     * 指定的用于项目外对象,无法添加@CurrencySymbolTrans注解的对象。
     * @return
     */
    String[] response() default {};
}

AOP切面

package com.das.aop;

import com.das.common.response.RestResponse;
import com.das.common.util.BeanInfoUtil;
import com.das.until.LittleBear;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Parameter;
import java.util.Arrays;

/**
 * @author liangmy
 * @date 2020/09/25
 */
@Slf4j
@Aspect
@Component
public class CurrencySymbolTransAspect {


    @Autowired
    private LittleBear littleBear;

    /**
     * 有可能栈溢出。具体问题具体分析
     *
     * @param proceedingJoinPoint
     * @return
     * @throws Throwable
     */
    @Around("within(@org.springframework.web.bind.annotation.RestController *) && @annotation(CurrencySymbolTrans)")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        // 获取方法签名
        MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();

        // 获取方法注解
        CurrencySymbolTrans annotationWithMethod = methodSignature.getMethod().getAnnotation(CurrencySymbolTrans.class);
        // 获取指定的用于项目外对象,无法添加@CurrencySymbolTrans注解的对象。
        String[] response = annotationWithMethod.response();

        // 获取方法签名形参列表
        Parameter[] parameters = methodSignature.getMethod().getParameters();
        // 获取方法签名形参值列表
        Object[] args = proceedingJoinPoint.getArgs();

        for (int i = 0; i < parameters.length; i++) {
            Parameter parameter = parameters[i];
            // 获取参数上的注解
            CurrencySymbolTrans annotation = parameter.getAnnotation(CurrencySymbolTrans.class);
            if (null != annotation) {
                Object arg = args[i];
                littleBear.currencySymbolTranstoForClass(arg);
                log.info("arg:{}", arg);
            }
        }


        log.info("args:{}", Arrays.toString(args));

        Object proceed = proceedingJoinPoint.proceed(args);

        if (proceed instanceof RestResponse) {
            RestResponse restResponse = (RestResponse) proceed;
            Object restResponseData = restResponse.getData();
            try {
                if (null != restResponseData) {
                    Object restResponseDataCopy = restResponseData.getClass().newInstance();
                    BeanInfoUtil.copyPropertiesDoDeepCopy(restResponseData, restResponseDataCopy);
                    littleBear.currencySymbolTransformForClass(restResponseDataCopy, response);
                    restResponse.setData(restResponseDataCopy);
                }
            } catch (Exception e) {
                littleBear.currencySymbolTransformForClass(restResponseData, response);
            }
        }
        return proceed;
    }

}

使用

1. 接口详情:返回结果包含需要转换的对象或域(无法使用注解时,使用@CurrencySymbolTrans注解中response字段标识)

    /**
     * liangmy
     *
     * @param receiveBaseId 接车单唯一标识
     * @param serviceCategoryName 服务类目
     * @param keyword 搜索关键字,非必传
     * @return
     */
    @CurrencySymbolTrans(response = {"charge", "children"})
    @ApiOperation(value = "查看标准服务变体树")
    @GetMapping(value = "/treeServiceVariantByReceiveBaseIdAndServiceCategoryName2")
    public RestResponse treeServiceVariantByReceiveBaseIdAndServiceCategoryName2(@RequestParam(value = "receiveBaseId") long receiveBaseId,
                                                                                 @RequestParam(value = "serviceCategoryName", required = false) ServiceCategoryEnum serviceCategoryName,
                                                                                 @RequestParam(required = false) String keyword) {
        ServiceNode serviceNode = orderManageService.treeServiceVariantByReceiveBaseIdAndServiceCategoryName2(receiveBaseId, serviceCategoryName, keyword, OperatorUtil.getBrandId());
        return RestResponse.successResponse(serviceNode);
    }
ServiceNode: 
package com.das.common.type;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author liangmy
 * @Date 2018/3/9
 */
public class ServiceNode {
    private String sn;
    private Long id;
    private String name;
    private Integer duration;
    private Integer deliveryDuration;
    private Integer skuAmount;
    private Double charge;
    /**
     * 是否缺失对应车型的工序模板 0 缺失 1 不缺失
     */
    private Boolean relationProcedureStatus;
    /**
     * 该服务下暂无匹配该车型的SKU
     */
    private Boolean deficiency;
    /**
     * 门店库存 不可实行的
     */
    private Boolean infeasible = true;
    /**
     * 仓库库存 不可实行的
     */
    private Boolean warehouseInfeasible = true;
    /**
     *
     */
    private Boolean selected = false;

    private Boolean checked;

    private Boolean standardStatus;

    private Long serviceNonstandardId;
    /**
     * 树高 根高度为0
     */
    private Integer depth;
    private List<ServiceNode> children;
    private static final Map<String, ServiceNode> nodeRepertory = new ConcurrentHashMap<>();
    private ServiceCategoryEnum serviceCategoryName;

    /**
     * ROOT
     */
    public ServiceNode() {
        this("", 0L, "全选", 0, 0, null, null, true, null, true, false, 0, false);
    }

    /**
     * ROOT
     *
     * @param selected
     */
    public ServiceNode(Boolean selected) {
        this("", 0L, "全选", 0, 0, null, null, true, null, true, selected, 0, false);
    }

    public ServiceNode(Integer depth) {
        this(depth, false);
    }

    public ServiceNode(Integer depth, boolean isLeaf) {
        this.depth = depth;
        if (!isLeaf) {
            children = new LinkedList<>();
        }
    }

    /**
     * BASE
     *
     * @param sn
     * @param id
     * @param name
     * @param duration
     * @param skuAmount
     * @param charge
     * @param relationProcedureStatus
     * @param infeasible
     * @param selected
     * @param depth
     * @param isLeaf
     */
    private ServiceNode(String sn, Long id, String name, Integer duration, Integer deliveryDuration, Integer skuAmount, Double charge, Boolean relationProcedureStatus, Boolean deficiency, Boolean infeasible, Boolean selected, Integer depth, boolean isLeaf) {
        this.sn = sn;
        this.id = id;
        this.name = name;
        this.duration = duration;
        this.skuAmount = skuAmount;
        this.charge = charge;
        this.relationProcedureStatus = relationProcedureStatus;
        this.deficiency = deficiency;
        this.deliveryDuration = deliveryDuration;
        this.infeasible = infeasible;
        this.selected = selected;
        this.depth = depth;
        if (!isLeaf) {
            children = new LinkedList<>();
        }
    }

    public void add(ServiceNode node) {
        if(null == node){
            return;
        }
        children.add(node);
//        nodeRepertory.put(node.getSn() + "-" + node.getDepth() + "-" + node.getName()  + "-" + node.getServiceNonstandardId(), node);
        nodeRepertory.put(node.getSn() + "-" + node.getDepth() + "-" + node.getName(), node);
    }

    public static Boolean containsKey(ServiceNode node) {
        if(null == node){
            return false;
        }
//        return nodeRepertory.containsKey(node.getSn() + "-" + node.getDepth() + "-" + node.getName() + "-" + node.getServiceNonstandardId());
        return nodeRepertory.containsKey(node.getSn() + "-" + node.getDepth() + "-" + node.getName());
    }

    public static ServiceNode search(ServiceNode node) {
        if(null == node){
            return null;
        }
//        return nodeRepertory.get(node.getSn() + "-" + node.getDepth() + "-" + node.getName() + "-" + node.getServiceNonstandardId());
        return nodeRepertory.get(node.getSn() + "-" + node.getDepth() + "-" + node.getName());
    }

    public static void clear() {
        nodeRepertory.clear();
    }

    public String getSn() {
        return sn;
    }

    public ServiceNode setSn(String sn) {
        this.sn = sn;
        return this;
    }

    public String getName() {
        return name;
    }

    public ServiceNode setName(String name) {
        this.name = name;
        return this;
    }

    public List<ServiceNode> getChildren() {
        return children;
    }

    public ServiceNode setChildren(List<ServiceNode> children) {
        this.children = children;
        return this;
    }

    public Boolean getSelected() {
        return selected;
    }

    public ServiceNode setSelected(Boolean selected) {
        if (null == selected) {
            this.selected = false;
        } else if (selected) {
            this.selected = selected;
        }
        return this;
    }

    public Integer getSkuAmount() {
        return skuAmount;
    }

    public ServiceNode setSkuAmount(Integer skuAmount) {
        this.skuAmount = skuAmount;
        return this;
    }

    public Double getCharge() {
        return charge;
    }

    public ServiceNode setCharge(Double charge) {
        this.charge = charge;
        return this;
    }

    public Integer getDuration() {
        return duration;
    }

    public ServiceNode setDuration(Integer duration) {
        this.duration = duration;
        return this;
    }

    public Boolean getInfeasible() {
        return infeasible;
    }

    public ServiceNode setInfeasible(Boolean infeasible) {
        if (null == infeasible) {
            this.infeasible = true;
        } else if (!infeasible) {
            this.infeasible = infeasible;
        }
        return this;
    }

    public Boolean getRelationProcedureStatus() {
        return relationProcedureStatus;
    }

    public ServiceNode setRelationProcedureStatus(Boolean relationProcedureStatus) {
        this.relationProcedureStatus = relationProcedureStatus;
        return this;
    }

    public Integer getDepth() {
        return depth;
    }

    public ServiceNode setDepth(Integer depth) {
        this.depth = depth;
        return this;
    }

    public Boolean getDeficiency() {
        return deficiency;
    }

    public ServiceNode setDeficiency(Boolean deficiency) {
        this.deficiency = deficiency;
        return this;
    }

    public Integer getDeliveryDuration() {
        return deliveryDuration;
    }

    public ServiceNode setDeliveryDuration(Integer deliveryDuration) {
        this.deliveryDuration = deliveryDuration;
        return this;
    }

    public ServiceNode setWarehouseInfeasible(Boolean warehouseInfeasible) {
        if(null == warehouseInfeasible){
            this.warehouseInfeasible = true;
        }else if(!warehouseInfeasible) {
            this.warehouseInfeasible = warehouseInfeasible;
        }
        return this;
    }

    public Boolean getWarehouseInfeasible() {
        return warehouseInfeasible;
    }

    public ServiceNode setId(Long id) {
        this.id = id;
        return this;
    }

    public Long getId() {
        return id;
    }

    public Boolean getChecked() {
        return checked;
    }

    public ServiceNode setChecked(Boolean checked) {
        this.checked = checked;
        return this;
    }

    public Long getServiceNonstandardId() {
        return serviceNonstandardId;
    }

    public ServiceNode setServiceNonstandardId(Long serviceNonstandardId) {
        this.serviceNonstandardId = serviceNonstandardId;
        return this;
    }

    public Boolean getStandardStatus() {
        return standardStatus;
    }

    public ServiceNode setStandardStatus(Boolean standardStatus) {
        this.standardStatus = standardStatus;
        return this;
    }

    public ServiceNode setServiceCategoryName(ServiceCategoryEnum serviceCategoryName) {
        this.serviceCategoryName = serviceCategoryName;
        return this;
    }

    public ServiceCategoryEnum getServiceCategoryName() {
        return serviceCategoryName;
    }
}

2. 接口详情:返回结果包含需要转换的对象或域(使用@CurrencySymbolTrans注解)

    /**
     * liangmy
     *
     * @param receiveBaseId 接车单唯一标识
     * @return
     */
    @CurrencySymbolTrans
    @ApiOperation(value = "查看接车单服务信息")
    @GetMapping(value = "/mapReceiveVariantAndStationStaff")
    public RestResponse mapReceiveVariantAndStationStaff(@RequestParam("receiveBaseId") Long receiveBaseId) {
        List<MapReceiveVariantAndStationStaffVO> mapReceiveVariantAndStationStaffVOList = orderManageService.mapReceiveVariantAndStationStaff(receiveBaseId, OperatorUtil.getBrandId());
        return RestResponse.successResponse(mapReceiveVariantAndStationStaffVOList);
    }
MapReceiveVariantAndStationStaffVO:
package com.das.vo.order;


import com.das.aop.CurrencySymbolTrans;
import com.das.entity.order.ReceiveVariantEntity;
import com.das.entity.order.WorkStaffEntity;
import lombok.Getter;
import lombok.Setter;

import java.util.Date;
import java.util.List;

/**
 * @Author : liangmy
 * @Description :
 * @Date : Created in 2020/09/27
 * @Modified By :
 */
@Getter
@Setter
public class MapReceiveVariantAndStationStaffVO {
    /**
     * 服务变体列表
     */
    @CurrencySymbolTrans
    private List<ReceiveVariantEntity> variantEntityList;
    /**
     * 接车单关联服务项目批次号
     */
    private Long receiveVariantGroupNo;
    /**
     * 预期时长
     */
    private Long predictDuration;
    /**
     * 实际时长
     */
    private Long actualDuration;
    /**
     * 占用时长
     */
    private Long occupyDuration;
    /**
     * 交车时长
     */
    private Long deliveryDuration;
    /**
     * 施工技师列表
     */
    private List<WorkStaffEntity> staffEntityList;
    /**
     * 施工单唯一标识
     */
    private Long workBaseId;
    /**
     * 施工单状态
     */
    private Integer workBaseStatus;
    /**
     * 施工单开始时间
     */
    private Date workBaseStartTime;
    /**
     * 施工单结束时间
     */
    private Date workBaseCompleteTime;
    /**
     * 施工单是否超时
     */
    private Boolean timeOut;
    /**
     * 施工单取消时间
     */
    private Date workBaseCancelTime;
    /**
     * 施工单施工技师人员数量限制
     */
    private Integer restrictNum;
    /**
     * 销售人员
     */
    private SaleStaffVO saleStaff;
    /**
     * 当前时间
     */
    private Date currDate;
    /**
     * 库存是否充足
     */
    private Boolean infeasible;

    @Getter
    @Setter
    public static class SaleStaffVO {
        /**
         * 销售技师唯一标识
         */
        private Long saleStaffId;
        /**
         * 销售技师名称
         */
        private String saleStaffName;
        /**
         * 销售技师头像URL
         */
        private String saleStaffUrl;
    }

}
ReceiveVariantEntity:
package com.das.entity.order;


import com.das.aop.CurrencySymbolTrans;
import lombok.Getter;
import lombok.Setter;
import org.springframework.data.annotation.Transient;

import java.util.*;

/**
 * @Author liangmy
 * @Date 2018/3/12
 */
@Getter
@Setter
public class ReceiveVariantEntity {

    /**
     * 服务变体商品总价
     * priceRange
     */
    @CurrencySymbolTrans
    private Double serviceVariantPrice;

    /**
     * 为了前端方便绑数据,后台计算服务费用放到serviceVariantCharge字段中
     * FIX : charge
     * EXTRA : priceRange + charge
     */
    @CurrencySymbolTrans
    private Double serviceVariantCharge;
    /**
     * 使用余额数量
     */
    @CurrencySymbolTrans
    private Double userMoney;
    /**
     * 折后实际支付费用
     */
    @CurrencySymbolTrans
    private Double actualExpenses;
    /**
     * 优惠减免金额
     */
    @Transient
    @CurrencySymbolTrans
    private Double preferentialExpenses;

}

 3. 接口详情:请求参数或请求体包含需要转换的对象或域

    /**
     * liangmy
     * 数据说明:
     * <p>
     * 1. defined_user:读取车主姓名、手机号、微信头像及昵称(若有);
     * 2. 本店本月的剩余余额赠送额度/元:读取确认赠送金额前的本店本月的剩余余额赠送额度;
     * 3. 赠送金额/元:格式为不大于本店本月的剩余余额赠送额度的1-5000的整数;默认为空;必填;
     * 4. 赠送理由:格式为文本,字数不超过100字;必填;
     * <p>
     * 交互说明:
     * <p>
     * 1. 确认按钮:若赠送金额符合条件且赠送理由不为空,则弹出弹窗提示“即将为[手机号]账号赠送[赠送金额]元余额,赠送后无法撤回,请再确认!”;确认后继续提示“赠送成功,系统已自动发送短信通知用户。用户使用该手机号登录车主APP或微信公众号即可查看~”;
     *
     * @param entity
     * @return
     */
    @CurrencySymbolTrans
    @ApiOperation(value = "branch - 接车单详情 - 订单详情 - 添加/编辑使用余额弹窗")
    @PostMapping(value = "/saveCreditPresent")
    public RestResponse saveCreditPresent(@RequestBody @CurrencySymbolTrans CreditPresentEntity entity) {
        entity.setBrandId(OperatorUtil.getBrandId());
        entity.setStoreBaseId(SystemUserUtil.getStoreBaseId());
        entity.setOperatorId(SystemUserUtil.getUserId());
        creditPresentManageService.saveCreditPresent(entity);
        return RestResponse.successResponse();
    }
package com.das.entity.credit;

import com.das.aop.CurrencySymbolTrans;
import lombok.Getter;
import lombok.Setter;

/**
 * @Author liangmy
 * @Date 2019/10/18
 */
@Getter
@Setter
public class CreditPresentEntity {
    /**
     * 赠送金额
     */
    @CurrencySymbolTrans
    private Double presentMoney;

}

啦啦啦

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值