|
@@ -0,0 +1,262 @@
|
|
|
|
|
+package com.fs.hisStore.util;
|
|
|
|
|
+
|
|
|
|
|
+import com.fs.common.utils.StringUtils;
|
|
|
|
|
+import lombok.Data;
|
|
|
|
|
+
|
|
|
|
|
+import java.util.*;
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 经营范围商品类型工具类
|
|
|
|
|
+ * 根据店铺经营范围关键字判定可选商品类型及所需资质证书
|
|
|
|
|
+ *
|
|
|
|
|
+ * @author fs
|
|
|
|
|
+ * @date 2025-11-01
|
|
|
|
|
+ */
|
|
|
|
|
+public class BusinessScopeProductTypeUtil {
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 商品类型常量
|
|
|
|
|
+ */
|
|
|
|
|
+ public static class ProductType {
|
|
|
|
|
+ public static final String CHINESE_MEDICINE = "中成药";
|
|
|
|
|
+ public static final String PRESCRIPTION_DRUG = "处方药";
|
|
|
|
|
+ public static final String CHINESE_MEDICINE_TABLET = "中药饮片";
|
|
|
|
|
+ public static final String HEALTH_PRODUCT = "保健食品";
|
|
|
|
|
+ public static final String MEDICAL_DEVICE_1 = "I类医疗器械";
|
|
|
|
|
+ public static final String MEDICAL_DEVICE_2 = "II类医疗器械";
|
|
|
|
|
+ public static final String MEDICAL_DEVICE_3 = "III类医疗器械";
|
|
|
|
|
+ public static final String OTC_A = "甲类非处方药";
|
|
|
|
|
+ public static final String OTC_B = "乙类非处方药";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 所需资质证书类型
|
|
|
|
|
+ */
|
|
|
|
|
+ public static class CertificateType {
|
|
|
|
|
+ public static final String BUSINESS_LICENSE = "营业执照";
|
|
|
|
|
+ public static final String DRUG_LICENSE = "药品经营许可证";
|
|
|
|
|
+ public static final String FOOD_LICENSE = "食品经营许可证";
|
|
|
|
|
+ public static final String MEDICAL_DEVICE_1_CERT = "第一类医疗器械备案凭证";
|
|
|
|
|
+ public static final String MEDICAL_DEVICE_2_CERT = "第二类医疗器械备案凭证";
|
|
|
|
|
+ public static final String MEDICAL_DEVICE_3_CERT = "第三类医疗器械注册证";
|
|
|
|
|
+ public static final String HEALTH_FOOD_CERT = "保健食品销售资质";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 商品类型配置信息
|
|
|
|
|
+ */
|
|
|
|
|
+ @Data
|
|
|
|
|
+ public static class ProductTypeConfig {
|
|
|
|
|
+ private String productType; // 商品类型
|
|
|
|
|
+ private List<String> keywords; // 经营范围关键字
|
|
|
|
|
+ private List<String> requiredCerts; // 所需资质证书
|
|
|
|
|
+
|
|
|
|
|
+ public ProductTypeConfig(String productType, List<String> keywords, List<String> requiredCerts) {
|
|
|
|
|
+ this.productType = productType;
|
|
|
|
|
+ this.keywords = keywords;
|
|
|
|
|
+ this.requiredCerts = requiredCerts;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 商品类型配置列表
|
|
|
|
|
+ * 根据表格配置:类目 -> 判定关键字 -> 所需资质证书
|
|
|
|
|
+ */
|
|
|
|
|
+ private static final List<ProductTypeConfig> PRODUCT_TYPE_CONFIGS = new ArrayList<>();
|
|
|
|
|
+
|
|
|
|
|
+ static {
|
|
|
|
|
+ // 中成药:判定=中成药,需要=药品经营许可证+营业执照
|
|
|
|
|
+ PRODUCT_TYPE_CONFIGS.add(new ProductTypeConfig(
|
|
|
|
|
+ ProductType.CHINESE_MEDICINE,
|
|
|
|
|
+ Arrays.asList("中成药"),
|
|
|
|
|
+ Arrays.asList(CertificateType.DRUG_LICENSE, CertificateType.BUSINESS_LICENSE)
|
|
|
|
|
+ ));
|
|
|
|
|
+
|
|
|
|
|
+ // 处方药:判定=处方药/化学药制剂,需要=药品经营许可证+营业执照
|
|
|
|
|
+ PRODUCT_TYPE_CONFIGS.add(new ProductTypeConfig(
|
|
|
|
|
+ ProductType.PRESCRIPTION_DRUG,
|
|
|
|
|
+ Arrays.asList("处方药", "化学药制剂"),
|
|
|
|
|
+ Arrays.asList(CertificateType.DRUG_LICENSE, CertificateType.BUSINESS_LICENSE)
|
|
|
|
|
+ ));
|
|
|
|
|
+
|
|
|
|
|
+ // 中药饮片:判定=中药饮片,需要=药品经营许可证+营业执照
|
|
|
|
|
+ PRODUCT_TYPE_CONFIGS.add(new ProductTypeConfig(
|
|
|
|
|
+ ProductType.CHINESE_MEDICINE_TABLET,
|
|
|
|
|
+ Arrays.asList("中药饮片"),
|
|
|
|
|
+ Arrays.asList(CertificateType.DRUG_LICENSE, CertificateType.BUSINESS_LICENSE)
|
|
|
|
|
+ ));
|
|
|
|
|
+
|
|
|
|
|
+ // 保健食品:判定=保健食品销售,需要=保健食品销售+营业执照
|
|
|
|
|
+ PRODUCT_TYPE_CONFIGS.add(new ProductTypeConfig(
|
|
|
|
|
+ ProductType.HEALTH_PRODUCT,
|
|
|
|
|
+ Arrays.asList("保健食品销售", "保健食品", "保健品"),
|
|
|
|
|
+ Arrays.asList(CertificateType.HEALTH_FOOD_CERT, CertificateType.BUSINESS_LICENSE)
|
|
|
|
|
+ ));
|
|
|
|
|
+
|
|
|
|
|
+ // I类医疗器械:判定=第一类医疗器械销售,需要=第一类医疗器械备案凭证+营业执照
|
|
|
|
|
+ PRODUCT_TYPE_CONFIGS.add(new ProductTypeConfig(
|
|
|
|
|
+ ProductType.MEDICAL_DEVICE_1,
|
|
|
|
|
+ Arrays.asList("第一类医疗器械销售", "一类医疗器械", "I类医疗器械", "1类医疗器械"),
|
|
|
|
|
+ Arrays.asList(CertificateType.MEDICAL_DEVICE_1_CERT, CertificateType.BUSINESS_LICENSE)
|
|
|
|
|
+ ));
|
|
|
|
|
+
|
|
|
|
|
+ // II类医疗器械:判定=第二类医疗器械销售,需要=第二类医疗器械备案凭证+营业执照
|
|
|
|
|
+ PRODUCT_TYPE_CONFIGS.add(new ProductTypeConfig(
|
|
|
|
|
+ ProductType.MEDICAL_DEVICE_2,
|
|
|
|
|
+ Arrays.asList("第二类医疗器械销售", "二类医疗器械", "II类医疗器械", "2类医疗器械"),
|
|
|
|
|
+ Arrays.asList(CertificateType.MEDICAL_DEVICE_2_CERT, CertificateType.BUSINESS_LICENSE)
|
|
|
|
|
+ ));
|
|
|
|
|
+
|
|
|
|
|
+ // III类医疗器械:判定=第三类医疗器械经营,需要=第三类医疗器械注册证+营业执照
|
|
|
|
|
+ PRODUCT_TYPE_CONFIGS.add(new ProductTypeConfig(
|
|
|
|
|
+ ProductType.MEDICAL_DEVICE_3,
|
|
|
|
|
+ Arrays.asList("第三类医疗器械经营", "三类医疗器械", "III类医疗器械", "3类医疗器械"),
|
|
|
|
|
+ Arrays.asList(CertificateType.MEDICAL_DEVICE_3_CERT, CertificateType.BUSINESS_LICENSE)
|
|
|
|
|
+ ));
|
|
|
|
|
+
|
|
|
|
|
+ // 甲类非处方药:判定=甲类非处方药/化学药制剂,需要=药品经营许可证+营业执照
|
|
|
|
|
+ PRODUCT_TYPE_CONFIGS.add(new ProductTypeConfig(
|
|
|
|
|
+ ProductType.OTC_A,
|
|
|
|
|
+ Arrays.asList("甲类非处方药", "甲类非处方", "甲类非处方药/化学药制剂"),
|
|
|
|
|
+ Arrays.asList(CertificateType.DRUG_LICENSE, CertificateType.BUSINESS_LICENSE)
|
|
|
|
|
+ ));
|
|
|
|
|
+
|
|
|
|
|
+ // 乙类非处方药:判定=乙类非处方药/化学药制剂,需要=药品经营许可证+营业执照
|
|
|
|
|
+ PRODUCT_TYPE_CONFIGS.add(new ProductTypeConfig(
|
|
|
|
|
+ ProductType.OTC_B,
|
|
|
|
|
+ Arrays.asList("乙类非处方药", "乙类非处方", "乙类非处方药/化学药制剂"),
|
|
|
|
|
+ Arrays.asList(CertificateType.DRUG_LICENSE, CertificateType.BUSINESS_LICENSE)
|
|
|
|
|
+ ));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 根据经营范围判定可选商品类型
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param businessScope 经营范围
|
|
|
|
|
+ * @return 可选商品类型列表,以逗号分隔的字符串
|
|
|
|
|
+ */
|
|
|
|
|
+ public static String determineProductTypes(String businessScope) {
|
|
|
|
|
+ if (StringUtils.isEmpty(businessScope)) {
|
|
|
|
|
+ return "";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Set<String> productTypes = new LinkedHashSet<>();
|
|
|
|
|
+
|
|
|
|
|
+ // 遍历所有配置,检查经营范围是否包含关键字
|
|
|
|
|
+ for (ProductTypeConfig config : PRODUCT_TYPE_CONFIGS) {
|
|
|
|
|
+ for (String keyword : config.getKeywords()) {
|
|
|
|
|
+ if (businessScope.contains(keyword)) {
|
|
|
|
|
+ productTypes.add(config.getProductType());
|
|
|
|
|
+ break; // 找到一个关键字即可,跳出内层循环
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 将商品类型集合转换为逗号分隔的字符串
|
|
|
|
|
+ return String.join(",", productTypes);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 根据经营范围判定所需的资质证书
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param businessScope 经营范围
|
|
|
|
|
+ * @return 所需资质证书列表,以逗号分隔的字符串
|
|
|
|
|
+ */
|
|
|
|
|
+ public static String determineRequiredCertificates(String businessScope) {
|
|
|
|
|
+ if (StringUtils.isEmpty(businessScope)) {
|
|
|
|
|
+ return "";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Set<String> certificates = new LinkedHashSet<>();
|
|
|
|
|
+ // 营业执照是必需的
|
|
|
|
|
+ certificates.add(CertificateType.BUSINESS_LICENSE);
|
|
|
|
|
+
|
|
|
|
|
+ // 遍历所有配置,收集所需资质证书
|
|
|
|
|
+ for (ProductTypeConfig config : PRODUCT_TYPE_CONFIGS) {
|
|
|
|
|
+ for (String keyword : config.getKeywords()) {
|
|
|
|
|
+ if (businessScope.contains(keyword)) {
|
|
|
|
|
+ certificates.addAll(config.getRequiredCerts());
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return String.join(",", certificates);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 根据商品类型获取所需的资质证书
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param productType 商品类型
|
|
|
|
|
+ * @return 所需资质证书列表
|
|
|
|
|
+ */
|
|
|
|
|
+ public static List<String> getRequiredCertificatesByProductType(String productType) {
|
|
|
|
|
+ if (StringUtils.isEmpty(productType)) {
|
|
|
|
|
+ return new ArrayList<>();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ for (ProductTypeConfig config : PRODUCT_TYPE_CONFIGS) {
|
|
|
|
|
+ if (config.getProductType().equals(productType)) {
|
|
|
|
|
+ return new ArrayList<>(config.getRequiredCerts());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return new ArrayList<>();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 将逗号分隔的字符串转换为商品类型列表
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param selectableProductTypes 逗号分隔的商品类型字符串
|
|
|
|
|
+ * @return 商品类型列表
|
|
|
|
|
+ */
|
|
|
|
|
+ public static List<String> parseProductTypes(String selectableProductTypes) {
|
|
|
|
|
+ if (StringUtils.isEmpty(selectableProductTypes)) {
|
|
|
|
|
+ return new ArrayList<>();
|
|
|
|
|
+ }
|
|
|
|
|
+ List<String> result = new ArrayList<>();
|
|
|
|
|
+ for (String type : selectableProductTypes.split(",")) {
|
|
|
|
|
+ if (StringUtils.isNotEmpty(type)) {
|
|
|
|
|
+ result.add(type.trim());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 检查商品类型是否在允许范围内
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param selectableProductTypes 店铺可选商品类型
|
|
|
|
|
+ * @param productType 待检查的商品类型
|
|
|
|
|
+ * @return true-允许 false-不允许
|
|
|
|
|
+ */
|
|
|
|
|
+ public static boolean isProductTypeAllowed(String selectableProductTypes, String productType) {
|
|
|
|
|
+ if (StringUtils.isEmpty(selectableProductTypes) || StringUtils.isEmpty(productType)) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ List<String> allowedTypes = parseProductTypes(selectableProductTypes);
|
|
|
|
|
+ return allowedTypes.contains(productType);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取所有商品类型列表
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return 商品类型列表
|
|
|
|
|
+ */
|
|
|
|
|
+ public static List<String> getAllProductTypes() {
|
|
|
|
|
+ List<String> types = new ArrayList<>();
|
|
|
|
|
+ for (ProductTypeConfig config : PRODUCT_TYPE_CONFIGS) {
|
|
|
|
|
+ types.add(config.getProductType());
|
|
|
|
|
+ }
|
|
|
|
|
+ return types;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取所有商品类型配置
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return 商品类型配置列表
|
|
|
|
|
+ */
|
|
|
|
|
+ public static List<ProductTypeConfig> getAllProductTypeConfigs() {
|
|
|
|
|
+ return new ArrayList<>(PRODUCT_TYPE_CONFIGS);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|