├── .gitattributes ├── .gitignore ├── .idea ├── .gitignore ├── JavaECM.iml ├── dbnavigator.xml ├── misc.xml └── vcs.xml ├── .mvn └── wrapper │ └── maven-wrapper.properties ├── MEMBER.md ├── README.md ├── docs └── images │ ├── 0001-vanhanh.png │ ├── 0002-shop-manager.png │ ├── 0003-user-manager.png │ └── 0004-product.png ├── mvnw ├── mvnw.cmd ├── myshop-framework ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── myshop │ ├── cache │ ├── Cache.java │ ├── CachePrefix.java │ ├── config │ │ └── redis │ │ │ ├── FastJsonRedisDataSerializer.java │ │ │ └── RedisConfiguration.java │ └── impl │ │ └── RedisCache.java │ ├── common │ ├── aop │ │ ├── annotation │ │ │ └── AntiDuplicateSubmission.java │ │ └── interceptor │ │ │ └── AntiDuplicateSubmissionInterceptor.java │ ├── context │ │ └── RequestScopeContext.java │ ├── enums │ │ ├── ClientType.java │ │ ├── ResultCode.java │ │ └── ResultUtil.java │ ├── exception │ │ ├── GlobalControllerExceptionHandler.java │ │ ├── RetryException.java │ │ └── ServiceException.java │ ├── properties │ │ ├── IgnoredUrlsProperties.java │ │ ├── JWTTokenProperties.java │ │ ├── SystemProperties.java │ │ └── ThreadPoolProperties.java │ ├── security │ │ ├── AuthUser.java │ │ ├── CustomAccessDeniedHandler.java │ │ ├── InvalidAuthenticationEntryPoint.java │ │ ├── OperationalAssessment.java │ │ ├── SecurityBean.java │ │ ├── context │ │ │ └── UserContext.java │ │ ├── enums │ │ │ ├── PermissionEnum.java │ │ │ ├── SecurityEnum.java │ │ │ └── UserEnums.java │ │ ├── sensitive │ │ │ ├── SensitiveData.java │ │ │ ├── SensitiveJsonSerializer.java │ │ │ └── enums │ │ │ │ └── SensitiveStrategy.java │ │ └── token │ │ │ ├── JwtTokenUtil.java │ │ │ ├── SecretKeyUtil.java │ │ │ ├── Token.java │ │ │ └── base │ │ │ └── TokenGeneratorBase.java │ ├── thread │ │ └── ThreadPoolConfig.java │ ├── utils │ │ ├── BeanUtil.java │ │ ├── CommonUtil.java │ │ ├── CookieUtil.java │ │ ├── ResponseUtil.java │ │ └── StringUtils.java │ ├── validation │ │ ├── EnumValue.java │ │ ├── Mobile.java │ │ └── impl │ │ │ ├── EnumValueChecker.java │ │ │ └── MobileValidator.java │ └── vo │ │ ├── PageVO │ │ └── PageVO.java │ │ └── ResultMessage.java │ ├── modules │ ├── member │ │ ├── entity │ │ │ ├── dos │ │ │ │ ├── Employee.java │ │ │ │ ├── Member.java │ │ │ │ ├── StoreMenu.java │ │ │ │ └── StoreRoleMenu.java │ │ │ ├── dto │ │ │ │ └── EmployeeAddDTO.java │ │ │ └── vo │ │ │ │ └── StoreMenuUserVO.java │ │ ├── mapper │ │ │ ├── EmployeeMapper.java │ │ │ ├── StoreMenuMapper.java │ │ │ └── StoreRoleMenuMapper.java │ │ ├── service │ │ │ ├── EmployeeService.java │ │ │ ├── MemberService.java │ │ │ ├── StoreMenuService.java │ │ │ ├── StoreRoleMenuService.java │ │ │ └── StoreRoleMenuServiceImpl.java │ │ ├── serviceimpl │ │ │ ├── EmployeeServiceImpl.java │ │ │ └── StoreMenuServiceImpl.java │ │ └── token │ │ │ ├── MemberTokenProvider.java │ │ │ └── StoreTokenProvider.java │ ├── permission │ │ ├── entity │ │ │ ├── dos │ │ │ │ ├── AdminUser.java │ │ │ │ └── Menu.java │ │ │ └── vo │ │ │ │ └── UserMenuVO.java │ │ ├── mapper │ │ │ ├── AdminUserMapper.java │ │ │ └── MenuMapper.java │ │ ├── service │ │ │ ├── AdminUserService.java │ │ │ └── MenuService.java │ │ └── serviceimpl │ │ │ ├── AdminUserServiceImpl.java │ │ │ └── MenuServiceImpl.java │ ├── product │ │ ├── entity │ │ │ ├── dos │ │ │ │ ├── Product.java │ │ │ │ ├── ProductBrand.java │ │ │ │ ├── ProductCategory.java │ │ │ │ ├── ProductCategoryBrand.java │ │ │ │ ├── ProductCategoryParameterGroup.java │ │ │ │ ├── ProductCategorySpecification.java │ │ │ │ ├── ProductGallery.java │ │ │ │ ├── ProductParameters.java │ │ │ │ ├── ProductSearchParams.java │ │ │ │ ├── ProductSku.java │ │ │ │ ├── ProductSpecification.java │ │ │ │ ├── ProductUnit.java │ │ │ │ └── Wholesale.java │ │ │ ├── dto │ │ │ │ ├── ProductBrandPageDTO.java │ │ │ │ ├── ProductCategorySearchParams.java │ │ │ │ ├── ProductImportDTO.java │ │ │ │ ├── ProductOperationDTO.java │ │ │ │ ├── ProductParamsDTO.java │ │ │ │ ├── ProductParamsItemDTO.java │ │ │ │ └── WholesaleDTO.java │ │ │ ├── enums │ │ │ │ ├── ProductAuthEnum.java │ │ │ │ ├── ProductSalesModeEnum.java │ │ │ │ ├── ProductStatusEnum.java │ │ │ │ └── ProductTypeEnum.java │ │ │ └── vos │ │ │ │ ├── ProductBrandVO.java │ │ │ │ ├── ProductCategoryVO.java │ │ │ │ ├── ProductParameterGroupVO.java │ │ │ │ ├── ProductSkuVO.java │ │ │ │ ├── ProductSpecValueVO.java │ │ │ │ └── ProductVO.java │ │ ├── mapper │ │ │ ├── CategoryMapper.java │ │ │ ├── MemberMapper.java │ │ │ ├── ProductBrandMapper.java │ │ │ ├── ProductCategoryBrandMapper.java │ │ │ ├── ProductCategoryParameterGroupMapper.java │ │ │ ├── ProductCategorySpecificationMapper.java │ │ │ ├── ProductGalleryMapper.java │ │ │ ├── ProductMapper.java │ │ │ ├── ProductParametersMapper.java │ │ │ ├── ProductSkuMapper.java │ │ │ ├── ProductSpecificationMapper.java │ │ │ └── ProductUnitMapper.java │ │ ├── service │ │ │ ├── ProductBrandService.java │ │ │ ├── ProductCategoryBrandService.java │ │ │ ├── ProductCategoryParameterGroupService.java │ │ │ ├── ProductCategoryService.java │ │ │ ├── ProductCategorySpecificationService.java │ │ │ ├── ProductGalleryService.java │ │ │ ├── ProductParametersService.java │ │ │ ├── ProductService.java │ │ │ ├── ProductSkuService.java │ │ │ ├── ProductSpecificationService.java │ │ │ └── ProductUnitService.java │ │ └── serviceimpl │ │ │ ├── MemberServiceImpl.java │ │ │ ├── ProductBrandServiceImpl.java │ │ │ ├── ProductCategoryBrandServiceImpl.java │ │ │ ├── ProductCategoryParameterGroupServiceImpl.java │ │ │ ├── ProductCategoryServiceImpl.java │ │ │ ├── ProductCategorySpecificationServiceImpl.java │ │ │ ├── ProductGalleryServiceImpl.java │ │ │ ├── ProductParametersServiceImpl.java │ │ │ ├── ProductServiceImpl.java │ │ │ ├── ProductSkuServiceImpl.java │ │ │ ├── ProductSpecificationServiceImpl.java │ │ │ └── ProductUnitServiceImpl.java │ ├── search │ │ └── utils │ │ │ └── SqlFilter.java │ ├── store │ │ ├── entity │ │ │ ├── dos │ │ │ │ └── Store.java │ │ │ ├── dto │ │ │ │ └── ManagementStoreApplyDTO.java │ │ │ ├── enums │ │ │ │ └── StoreStatusEnum.java │ │ │ └── vos │ │ │ │ └── StoreVO.java │ │ ├── mapper │ │ │ └── StoreMapper.java │ │ └── service │ │ │ ├── StoreService.java │ │ │ └── StoreServiceImpl.java │ └── system │ │ ├── entity │ │ ├── dos │ │ │ └── Setting.java │ │ ├── dto │ │ │ └── ProductSetting.java │ │ └── enums │ │ │ └── SettingEnum.java │ │ ├── mapper │ │ └── SettingMapper.java │ │ ├── service │ │ └── SettingService.java │ │ ├── serviceimpl │ │ └── SettingServiceImpl.java │ │ └── token │ │ └── ManagerTokenProvider.java │ └── orm │ ├── BaseEntity.java │ ├── IdBasedEntity.java │ ├── mybatisplus │ ├── MybatisObjectHandler.java │ ├── MybatisPlusConfig.java │ └── external │ │ ├── BulkInsertIgnoreAll.java │ │ ├── CustomBaseMapper.java │ │ └── CustomSqlInjector.java │ └── util │ └── PageUtil.java ├── myshop-module-buyer ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── myshop │ ├── BuyerApplicationApi.java │ ├── controller │ ├── identity │ │ ├── BuyerMemberController.java │ │ └── ProductCategoryBuyerController.java │ └── product │ │ └── ProductBuyerController.java │ └── security │ ├── AuthenticationFilterForBuyer.java │ └── SecurityConfigForBuyer.java ├── myshop-module-manager ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── myshop │ │ ├── ManagerApplicationApi.java │ │ ├── controller │ │ ├── identity │ │ │ └── AdminUserManagementController.java │ │ └── product │ │ │ ├── ProductBrandManagerController.java │ │ │ ├── ProductCategoryManagerController.java │ │ │ ├── ProductCategoryParameterGroupManagerController.java │ │ │ ├── ProductManagerController.java │ │ │ ├── ProductParameterManagerController.java │ │ │ ├── ProductSpecificationManagerController.java │ │ │ └── ProductUnitManagerController.java │ │ └── security │ │ ├── AuthenticationFilterForManagement.java │ │ └── SecurityConfigForManagement.java │ └── resources │ └── application.yml ├── myshop-module-store ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── myshop │ │ ├── StoreApplicationApi.java │ │ ├── controller │ │ └── product │ │ │ ├── ProductCategoryParameterGroupStoreController.java │ │ │ ├── ProductSpecificationStoreController.java │ │ │ ├── ProductStoreController.java │ │ │ └── ProductUnitStoreController.java │ │ └── security │ │ ├── AuthenticationFilterForStore.java │ │ └── SecurityConfigForStore.java │ └── resources │ └── application.yml └── pom.xml /.gitattributes: -------------------------------------------------------------------------------- 1 | /mvnw text eol=lf 2 | *.cmd text eol=crlf 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !../.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/JavaECM.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | wrapperVersion=3.3.2 18 | distributionType=only-script 19 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip 20 | distributionSha256Sum=4ec3f26fb1a692473aea0235c300bd20f0f9fe741947c82c1234cefd76ac3a3c 21 | -------------------------------------------------------------------------------- /MEMBER.md: -------------------------------------------------------------------------------- 1 | ## Danh sách các member tham gia dự án JAVA ECOMMERCE BACKEND 2 | 3 | 1. Anonystick 4 | 5 | - [Github](https://github.com/anonystick) 6 | - [Youtube](https://www.youtube.com/@anonystick) 7 | - [Profile](https://anonystick.com) 8 | 9 | 2. VanTrang 10 | 11 | - [Github](https://github.com/VanTrangDinh) 12 | - [Youtube]() 13 | - [Profile]() 14 | -------------------------------------------------------------------------------- /docs/images/0001-vanhanh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anonystick/JAVA-ecommerce-backend-api-MEMBER/874cb3e2a133d9e4678dde9da9cf28999adcbd67/docs/images/0001-vanhanh.png -------------------------------------------------------------------------------- /docs/images/0002-shop-manager.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anonystick/JAVA-ecommerce-backend-api-MEMBER/874cb3e2a133d9e4678dde9da9cf28999adcbd67/docs/images/0002-shop-manager.png -------------------------------------------------------------------------------- /docs/images/0003-user-manager.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anonystick/JAVA-ecommerce-backend-api-MEMBER/874cb3e2a133d9e4678dde9da9cf28999adcbd67/docs/images/0003-user-manager.png -------------------------------------------------------------------------------- /docs/images/0004-product.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anonystick/JAVA-ecommerce-backend-api-MEMBER/874cb3e2a133d9e4678dde9da9cf28999adcbd67/docs/images/0004-product.png -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/cache/Cache.java: -------------------------------------------------------------------------------- 1 | package com.myshop.cache; 2 | 3 | import java.util.Collection; 4 | import java.util.List; 5 | import java.util.concurrent.TimeUnit; 6 | 7 | /** 8 | * Interface cache 9 | * 10 | * @author vantrang 11 | */ 12 | public interface Cache { 13 | 14 | /** 15 | * Lấy một mục từ cache, không giao dịch. 16 | * 17 | * @param key Khóa cache 18 | * @return Đối tượng được lưu trong cache hoặc null 19 | */ 20 | T get(Object key); 21 | 22 | /** 23 | * Thêm một mục vào bộ nhớ cache, phi giao dịch, với 24 | * ngữ nghĩa thất bại nhanh 25 | * 26 | * @param key Khóa cache 27 | * @param value Giá trị cache 28 | */ 29 | void put(Object key, T value); 30 | 31 | /** 32 | * Ghi nội dung vào bộ nhớ cache 33 | * 34 | * @param key Khóa cache 35 | * @param value Giá trị cache 36 | * @param exp Thời gian hết hạn, đơn vị là giây 37 | */ 38 | void put(Object key, T value, Long exp); 39 | 40 | /** 41 | * Ghi nội dung vào bộ nhớ cache 42 | * 43 | * @param key Khóa cache 44 | * @param value Giá trị cache 45 | * @param exp Thời gian hết hạn 46 | * @param timeUnit Đơn vị thời gian hết hạn 47 | */ 48 | void put(Object key, T value, Long exp, TimeUnit timeUnit); 49 | 50 | /** 51 | * Kiểm tra xem có chứa khóa hay không 52 | * 53 | * @param key Khóa cache 54 | * @return True nếu có chứa khóa, False nếu không 55 | */ 56 | boolean hasKey(Object key); 57 | 58 | /** 59 | * Xóa 60 | * 61 | * @param key Khóa cache 62 | */ 63 | Boolean remove(Object key); 64 | 65 | /** 66 | * Bộ đếm redis tăng thêm 67 | * Lưu ý: Sau khi đạt đến liveTime, lần tăng thêm này sẽ bị hủy bỏ, tức là tự động -1, thay vì giá trị redis rỗng 68 | * 69 | * @param key Là key cộng dồn, cùng một key mỗi lần gọi thì giá trị +1 70 | * @param liveTime Đơn vị giây sau khi hết hạn 71 | * @return Kết quả bộ đếm 72 | */ 73 | Long increment(String key, long liveTime); 74 | 75 | /** 76 | * Xóa hàng loạt 77 | * 78 | * @param keys Tập hợp các khóa cần xóa 79 | */ 80 | void batchDelete(Collection keys); 81 | } 82 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/cache/CachePrefix.java: -------------------------------------------------------------------------------- 1 | package com.myshop.cache; 2 | 3 | 4 | import com.myshop.common.security.enums.UserEnums; 5 | 6 | public enum CachePrefix { 7 | 8 | /** 9 | * Cây phân cấp danh mục sản phẩm 10 | */ 11 | PRODUCT_CATEGORY, 12 | 13 | /** 14 | * Danh sách danh mục sản phẩm 15 | */ 16 | CATEGORY_ARRAY, 17 | 18 | 19 | /** 20 | * Store user menu 21 | */ 22 | STORE_MENU_USER, 23 | 24 | /** 25 | * Permissions 26 | */ 27 | PERMISSION_LIST, 28 | /** 29 | * Inviter 30 | */ 31 | INVITER, 32 | /** 33 | * access token 34 | */ 35 | ACCESS_TOKEN, 36 | /** 37 | * refresh token 38 | */ 39 | REFRESH_TOKEN, 40 | 41 | /** 42 | * San pham 43 | */ 44 | PRODUCT, 45 | 46 | /** 47 | * Product sku 48 | */ 49 | PRODUCT_SKU; 50 | 51 | 52 | public static String removePrefix(String string) { 53 | return string.substring(string.lastIndexOf("}_") + 2); 54 | } 55 | 56 | /** 57 | * Lấy giá trị khóa cache chung 58 | * 59 | * @return Giá trị khóa cache 60 | */ 61 | public String getPrefix() { 62 | return "{" + this.name() + "}_"; 63 | } 64 | 65 | /** 66 | * Lấy giá trị khóa cache + phía người dùng 67 | * Ví dụ: Ba nền tảng đều có hệ thống người dùng, cần đăng nhập riêng biệt, nếu tên người dùng trùng nhau, quyền hạn trong Redis có thể xảy ra xung đột. 68 | * 69 | * @param userEnum Vai trò 70 | * @return Giá trị khóa cache + phía người dùng 71 | */ 72 | public String getPrefix(UserEnums userEnum) { 73 | return "{" + this.name() + "_" + userEnum.name() + "}_"; 74 | } 75 | 76 | /** 77 | * Lấy giá trị khóa cache + phía người dùng + tiền tố tùy chỉnh 78 | * Ví dụ: Ba nền tảng đều có hệ thống người dùng, cần đăng nhập riêng biệt, nếu tên người dùng trùng nhau, quyền hạn trong Redis có thể xảy ra xung đột. 79 | * 80 | * @param userEnum Vai trò 81 | * @param customPrefix Tiền tố tùy chỉnh 82 | * @return Giá trị khóa cache 83 | */ 84 | public String getPrefix(UserEnums userEnum, String customPrefix) { 85 | return "{" + this.name() + "_" + userEnum.name() + "}_" + customPrefix + "_"; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/cache/config/redis/FastJsonRedisDataSerializer.java: -------------------------------------------------------------------------------- 1 | package com.myshop.cache.config.redis; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.alibaba.fastjson.serializer.SerializerFeature; 5 | import org.springframework.data.redis.serializer.RedisSerializer; 6 | import org.springframework.data.redis.serializer.SerializationException; 7 | 8 | import java.nio.charset.Charset; 9 | import java.nio.charset.StandardCharsets; 10 | 11 | /** 12 | * Để thực hiện cache đối tượng, bạn cần định nghĩa bộ serializer và deserializer riêng của mình. 13 | * Thường thì sử dụng thư viện fastjson của Alibaba để thực hiện. 14 | * 15 | * @author vantrang 16 | */ 17 | public class FastJsonRedisDataSerializer implements RedisSerializer { 18 | private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; 19 | private final Class clazz; 20 | 21 | public FastJsonRedisDataSerializer(Class clazz) { 22 | super(); 23 | this.clazz = clazz; 24 | } 25 | 26 | @Override 27 | public byte[] serialize(T t) throws SerializationException { 28 | if (null == t) { 29 | return new byte[0]; 30 | } 31 | // Sử dụng FastJson để serialize đối tượng thành chuỗi JSON. 32 | // WriteClassName đảm bảo rằng tên lớp được bao gồm trong JSON, điều này rất quan trọng cho việc deserialize. 33 | // DisableCircularReferenceDetect xử lý các tham chiếu vòng, ngăn ngừa lỗi tràn stack. 34 | return JSON.toJSONString(t, 35 | SerializerFeature.WriteClassName, 36 | SerializerFeature.DisableCircularReferenceDetect) 37 | .getBytes(DEFAULT_CHARSET);// Mã hóa chuỗi JSON thành byte sử dụng UTF-8 38 | } 39 | 40 | @Override 41 | public T deserialize(byte[] bytes) throws SerializationException { 42 | if (null == bytes || bytes.length <= 0) { 43 | return null; 44 | } 45 | String str = new String(bytes, DEFAULT_CHARSET);// Giải mã mảng byte thành chuỗi sử dụng UTF-8. 46 | // Sử dụng FastJson để deserialize chuỗi JSON thành một đối tượng của lớp được chỉ định. 47 | return (T) JSON.parseObject(str, clazz); 48 | } 49 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/cache/impl/RedisCache.java: -------------------------------------------------------------------------------- 1 | package com.myshop.cache.impl; 2 | 3 | import com.myshop.cache.Cache; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.data.redis.core.RedisTemplate; 7 | import org.springframework.data.redis.support.atomic.RedisAtomicLong; 8 | import org.springframework.stereotype.Component; 9 | 10 | import java.util.Collection; 11 | import java.util.concurrent.TimeUnit; 12 | 13 | @Slf4j 14 | @Component 15 | public class RedisCache implements Cache { 16 | 17 | @Autowired 18 | private RedisTemplate redisTemplate; 19 | 20 | public RedisCache() { 21 | } 22 | 23 | @Override 24 | public Object get(Object key) { 25 | return redisTemplate.opsForValue().get(key); 26 | } 27 | 28 | @Override 29 | public void put(Object key, Object value) { 30 | redisTemplate.opsForValue().set(key, value); 31 | } 32 | 33 | @Override 34 | public void put(Object key, Object value, Long exp) { 35 | put(key, value, exp, TimeUnit.SECONDS); 36 | } 37 | 38 | /** 39 | * Lưu trữ giá trị vào Redis với thời hạn hiệu lực. 40 | * 41 | * @param key Khóa của giá trị 42 | * @param value Giá trị cần lưu trữ 43 | * @param ttl Thời hạn hiệu lực 44 | * @param timeUnit Đơn vị thời gian cho thời hạn hiệu lực 45 | */ 46 | @Override 47 | public void put(Object key, Object value, Long ttl, TimeUnit timeUnit) { 48 | redisTemplate.opsForValue().set(key, value, ttl, timeUnit); 49 | } 50 | 51 | @Override 52 | public boolean hasKey(Object key) { 53 | return this.redisTemplate.opsForValue().get(key) != null; 54 | } 55 | 56 | @Override 57 | public Boolean remove(Object key) { 58 | return redisTemplate.delete(key); 59 | } 60 | 61 | @Override 62 | public Long increment(String key, long liveTime) { 63 | RedisAtomicLong atomicCounter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory()); 64 | Long counterValue = atomicCounter.getAndIncrement(); 65 | //Thiết lập thời gian hết hạn ban đầu 66 | if (counterValue == 0 && liveTime > 0) { 67 | atomicCounter.expire(liveTime, TimeUnit.SECONDS); 68 | } 69 | return counterValue; 70 | } 71 | 72 | @Override 73 | public void batchDelete(Collection keys) { 74 | redisTemplate.delete(keys); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/aop/annotation/AntiDuplicateSubmission.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.aop.annotation; 2 | 3 | 4 | import java.lang.annotation.*; 5 | 6 | /** 7 | * Chống tránh trùng lặp nộp gửi chú thích 8 | */ 9 | @Target(ElementType.METHOD) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Documented 12 | @Inherited 13 | public @interface AntiDuplicateSubmission { 14 | 15 | 16 | /** 17 | * Thời gian hết hạn mặc định là 3 giây, tức là không thể nhấp lại trong vòng 3 giây. 18 | */ 19 | long expire() default 3; 20 | 21 | /** 22 | * Cách ly giữa các người dùng, mặc định là false. 23 | * Nếu là true, thì giới hạn toàn cục, nếu là true thì cần trạng thái đăng nhập của người dùng, nếu không thì cách ly toàn cục 24 | */ 25 | boolean userSpecific() default false; 26 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/context/RequestScopeContext.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.context; 2 | 3 | import jakarta.servlet.http.HttpServletRequest; 4 | import jakarta.servlet.http.HttpServletResponse; 5 | import org.springframework.web.context.request.RequestContextHolder; 6 | import org.springframework.web.context.request.ServletRequestAttributes; 7 | 8 | 9 | /** 10 | * Công cụ lấy request / response 11 | **/ 12 | public class RequestScopeContext { 13 | 14 | public static HttpServletResponse getHttpResponse() { 15 | ServletRequestAttributes reqAttrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); 16 | assert reqAttrs != null; 17 | return reqAttrs.getResponse(); 18 | } 19 | 20 | public static HttpServletRequest getHttpRequest() { 21 | ServletRequestAttributes reqAttrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); 22 | assert reqAttrs != null; 23 | return reqAttrs.getRequest(); 24 | } 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/enums/ClientType.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.enums; 2 | 3 | /** 4 | * Client Type Enum 5 | */ 6 | 7 | public enum ClientType { 8 | /** 9 | * "Máy tính cá nhân" 10 | */ 11 | PC("Máy tính cá nhân"), 12 | /** 13 | * "Chương trình nhỏ" 14 | */ 15 | MINI_APP("Chương trình nhỏ Zalo"), 16 | /** 17 | * "Ứng dụng di động" 18 | */ 19 | APP("Ứng dụng di động"), 20 | /** 21 | * "Không xác định" 22 | */ 23 | UNKNOWN("Không xác định"); 24 | 25 | private String clientName; 26 | 27 | ClientType(String description) { 28 | this.clientName = description; 29 | } 30 | 31 | public String clientName() { 32 | return this.clientName; 33 | } 34 | 35 | public String value() { 36 | return this.name(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/exception/RetryException.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.exception; 2 | 3 | import lombok.Data; 4 | import lombok.EqualsAndHashCode; 5 | 6 | /** 7 | * Ném ngoại lệ này nếu cần retry 8 | * 9 | * @author vantrang 10 | * @since 2024/10/22 11 | **/ 12 | @EqualsAndHashCode(callSuper = true) 13 | @Data 14 | public class RetryException extends RuntimeException { 15 | // Biến serialVersionUID được sử dụng để xác định phiên bản của lớp này khi được serialize 16 | private static final long serialVersionUID = 7886918292771470846L; 17 | 18 | public RetryException(String msg) { 19 | super(msg); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/exception/ServiceException.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.exception; 2 | 3 | import com.myshop.common.enums.ResultCode; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | 7 | /** 8 | * Lớp ngoại lệ nghiệp vụ toàn cục 9 | * 10 | * @author vantrang 11 | */ 12 | @EqualsAndHashCode(callSuper = true) 13 | @Data 14 | public class ServiceException extends RuntimeException { 15 | 16 | // Biến serialVersionUID được sử dụng để xác định phiên bản của lớp này khi được serialize 17 | private static final long serialVersionUID = 3447728300174142127L; 18 | 19 | public static final String DEFAULT_MESSAGE = "Lỗi mạng, vui lòng thử lại sau!"; 20 | 21 | /** 22 | * Thông báo lỗi 23 | */ 24 | private String msg = DEFAULT_MESSAGE; 25 | 26 | /** 27 | * Mã lỗi 28 | */ 29 | private ResultCode resultCode; 30 | 31 | public ServiceException(String msg) { 32 | // Mặc định mã lỗi là ERROR 33 | this.resultCode = ResultCode.ERROR; 34 | this.msg = msg; 35 | } 36 | 37 | /** 38 | * Constructor tạo ngoại lệ mặc định. 39 | */ 40 | public ServiceException() { 41 | super(); 42 | } 43 | 44 | /** 45 | * Constructor tạo ngoại lệ với mã lỗi được cung cấp. 46 | * 47 | * @param code Mã lỗi 48 | */ 49 | public ServiceException(ResultCode code) { 50 | this.resultCode = code; 51 | } 52 | 53 | /** 54 | * Constructor tạo ngoại lệ với mã lỗi và thông báo lỗi được cung cấp. 55 | * 56 | * @param resultCode Mã lỗi 57 | * @param msg Thông báo lỗi 58 | */ 59 | public ServiceException(ResultCode resultCode, String msg) { 60 | this.resultCode = resultCode; 61 | this.msg = msg; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/properties/IgnoredUrlsProperties.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.properties; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | /** 11 | * Ignore authorization settings 12 | * 13 | * @author vantrang 14 | */ 15 | @Data 16 | @Configuration 17 | @ConfigurationProperties(prefix = "ignored") 18 | public class IgnoredUrlsProperties { 19 | private List urls = new ArrayList<>(); 20 | } 21 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/properties/JWTTokenProperties.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.properties; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | /** 8 | * Cấu hình hết hạn token 9 | * 10 | * @author vantrang 11 | */ 12 | @Data 13 | @Configuration 14 | @ConfigurationProperties(prefix = "myshop.jwt-setting") 15 | public class JWTTokenProperties { 16 | 17 | /** 18 | * Thời gian hết hạn mặc định của token 19 | */ 20 | private long tokenExpireTime = 60; 21 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/properties/SystemProperties.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.properties; 2 | 3 | 4 | import lombok.Data; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | /** 9 | * Cài đặt hệ thống 10 | */ 11 | @Data 12 | @Configuration 13 | @ConfigurationProperties(prefix = "myshop.system") 14 | public class SystemProperties { 15 | 16 | 17 | /** 18 | * Chế độ demo 19 | */ 20 | private Boolean demoMode = false; 21 | 22 | /** 23 | * Chế độ thử nghiệm 24 | * Mã xác thực SMS là 6 chữ số 1 25 | */ 26 | private Boolean testMode = false; 27 | 28 | /** 29 | * Mức độ ẩn thông tin: 30 | * 0: Không ẩn thông tin 31 | * 1: Ẩn thông tin của người dùng quản trị (như số điện thoại) 32 | * 2: Ẩn thông tin của cửa hàng (nếu là 2, thì cả quản trị và cửa hàng đều ẩn thông tin) 33 | *

34 | * PS: 35 | */ 36 | private Integer dataMaskingLevel = 0; 37 | 38 | 39 | public Boolean getDemoMode() { 40 | if (demoMode == null) { 41 | return false; 42 | } 43 | return demoMode; 44 | } 45 | 46 | public Boolean getTestMode() { 47 | if (testMode == null) { 48 | return false; 49 | } 50 | return testMode; 51 | } 52 | 53 | public Integer getDataMaskingLevel() { 54 | if (dataMaskingLevel == null) { 55 | return 0; 56 | } 57 | return dataMaskingLevel; 58 | } 59 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/properties/ThreadPoolProperties.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.properties; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | /** 8 | * Cấu hình luồng 9 | */ 10 | @Data 11 | @Configuration 12 | @ConfigurationProperties(prefix = "myshop.thread") 13 | public class ThreadPoolProperties { 14 | 15 | 16 | /** 17 | * Số lượng luồng core 18 | */ 19 | private Integer corePoolSize = 10; 20 | 21 | /** 22 | * Số lượng luồng tối đa 23 | */ 24 | private Integer maxPoolSize = 50; 25 | 26 | /** 27 | * Độ dài tối đa của hàng đợi 28 | */ 29 | private Integer queueCapacity = Integer.MAX_VALUE; 30 | 31 | /** 32 | * Cho phép đóng luồng hết thời gian chờ 33 | */ 34 | private Boolean allowCoreThreadTimeOut = false; 35 | 36 | /** 37 | * Keep Alive 38 | */ 39 | private Integer keepAliveSeconds = 60; 40 | 41 | 42 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/security/AuthUser.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.security; 2 | 3 | import com.myshop.common.security.enums.UserEnums; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import java.io.Serializable; 10 | 11 | /** 12 | * @author vantrang 13 | */ 14 | @Data 15 | @NoArgsConstructor 16 | @AllArgsConstructor 17 | @Builder 18 | public class AuthUser implements Serializable { 19 | 20 | private static final long serialVersionUID = 582441893336003319L; 21 | 22 | /** 23 | * username 24 | */ 25 | private String username; 26 | 27 | /** 28 | * nickname 29 | */ 30 | private String nickName; 31 | 32 | /** 33 | * avatar 34 | */ 35 | private String face; 36 | 37 | /** 38 | * id 39 | */ 40 | private String id; 41 | 42 | /** 43 | * Có hiệu lực trong thời gian dài (được sử dụng trong các tình huống đăng nhập ứng dụng di động hoặc các tình huống tin cậy, v.v.) 44 | */ 45 | private Boolean longTerm = false; 46 | 47 | /** 48 | * @see UserEnums 49 | * Vai trò 50 | */ 51 | private UserEnums role; 52 | 53 | /** 54 | * Nếu vai trò là người bán, trường id cửa hàng này sẽ tồn tại 55 | * storeId 56 | */ 57 | private String storeId; 58 | /** 59 | * Nếu vai trò là người bán thì trường id cửa hàng này sẽ tồn tại 60 | * clerkId 61 | */ 62 | private String clerkId; 63 | 64 | /** 65 | * Nếu vai trò là người bán thì trường tên cửa hàng này sẽ tồn tại 66 | * storeName 67 | */ 68 | private String storeName; 69 | 70 | /** 71 | * Có phải là siêu quản trị viên không? 72 | */ 73 | private Boolean isSuper = false; 74 | 75 | /** 76 | * id tenant 77 | */ 78 | private String tenantId; 79 | 80 | 81 | /** 82 | * // Khai báo constructor của lớp AuthUser, nhận vào các tham số: username, id, nickName, face, role 83 | * 84 | * @param username 85 | * @param id 86 | * @param nickName 87 | * @param face 88 | * @param role 89 | */ 90 | public AuthUser(String username, String id, String nickName, String face, UserEnums role) { 91 | // Gán giá trị cho thuộc tính username,... 92 | this.username = username; 93 | this.face = face; 94 | this.id = id; 95 | this.role = role; 96 | this.nickName = nickName; 97 | } 98 | 99 | 100 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/security/CustomAccessDeniedHandler.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.security; 2 | 3 | import com.myshop.common.utils.ResponseUtil; 4 | import jakarta.servlet.http.HttpServletRequest; 5 | import jakarta.servlet.http.HttpServletResponse; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.security.access.AccessDeniedException; 8 | import org.springframework.security.web.access.AccessDeniedHandler; 9 | import org.springframework.stereotype.Component; 10 | 11 | 12 | /** 13 | * Trình xử lý truy cập bị từ chối tùy chỉnh 14 | * 15 | * @author vantrang 16 | */ 17 | @Component 18 | @Slf4j 19 | public class CustomAccessDeniedHandler implements AccessDeniedHandler { 20 | 21 | @Override 22 | public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) { 23 | // Xuất ra phản hồi cho client khi truy cập bị từ chối. 24 | ResponseUtil.output(response, ResponseUtil.resultMap(false, 401, "Xin lỗi, bạn không có quyền truy cập")); 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/security/InvalidAuthenticationEntryPoint.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.security; 2 | 3 | import com.myshop.common.utils.ResponseUtil; 4 | import jakarta.servlet.http.HttpServletRequest; 5 | import jakarta.servlet.http.HttpServletResponse; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.security.core.AuthenticationException; 8 | import org.springframework.security.web.AuthenticationEntryPoint; 9 | import org.springframework.stereotype.Component; 10 | 11 | import java.io.IOException; 12 | 13 | @Slf4j 14 | @Component 15 | public class InvalidAuthenticationEntryPoint implements AuthenticationEntryPoint { 16 | 17 | @Override 18 | public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException { 19 | log.warn("Unauthorized => {}", request.getRequestURI()); 20 | ResponseUtil.output(response, ResponseUtil.resultMap(false, HttpServletResponse.SC_UNAUTHORIZED, "You do not have access rights!")); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/security/OperationalAssessment.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.security; 2 | 3 | import com.myshop.common.enums.ResultCode; 4 | import com.myshop.common.exception.ServiceException; 5 | import com.myshop.common.security.context.UserContext; 6 | import com.myshop.common.utils.BeanUtil; 7 | 8 | import java.util.Objects; 9 | 10 | /** 11 | * Xác định toàn cục xem có thể thao tác thuộc tính nào không 12 | */ 13 | public class OperationalAssessment { 14 | 15 | /** 16 | * Đối tượng cần xác định phải chứa thuộc tính memberId, storeId đại diện cho vai trò được xác định 17 | * 18 | * @param object Đối tượng được xác định 19 | * @param Loại đối tượng được xác định 20 | * @return Kết quả xử lý 21 | */ 22 | public static T judgment(T object) { 23 | // Gọi phương thức judgment với đối tượng object và các tên trường mặc định "memberId" và "storeId" 24 | return judgment(object, "memberId", "storeId"); 25 | } 26 | 27 | /** 28 | * Đối tượng cần xác định phải chứa thuộc tính memberId, storeId đại diện cho vai trò được xác định 29 | * 30 | * @param object Đối tượng được xác định 31 | * @param buyerIdField ID người mua 32 | * @param storeIdField ID cửa hàng 33 | * @param Loại đối tượng 34 | * @return Trả về bản thân đối tượng đã được xác định, tránh việc truy vấn đối tượng nhiều lần 35 | */ 36 | public static T judgment(T object, String buyerIdField, String storeIdField) { 37 | // Lấy đối tượng AuthUser của người dùng hiện tại từ UserContext và kiểm tra xem nó có null hay không 38 | AuthUser tokenUser = Objects.requireNonNull(UserContext.getCurrentUser()); 39 | // Kiểm tra vai trò của người dùng 40 | switch (tokenUser.getRole()) { 41 | // Nếu người dùng là MANAGER 42 | case MANAGER: 43 | return object; 44 | // Nếu người dùng là MEMBER 45 | case MEMBER: 46 | // Kiểm tra xem ID của người dùng hiện tại có khớp với giá trị của trường buyerIdField trong đối tượng object hay 47 | if (tokenUser.getId().equals(BeanUtil.getFieldValueByName(buyerIdField, object))) { 48 | // Nếu khớp, trả về đối tượng object 49 | return object; 50 | } else { 51 | throw new ServiceException(ResultCode.USER_PERMISSION_ERROR); 52 | } 53 | // Nếu người dùng là STORE 54 | case STORE: 55 | // Kiểm tra xem storeId của người dùng hiện tại có khớp với giá trị của trường storeIdField trong đối tượng 56 | if (tokenUser.getStoreId().equals(BeanUtil.getFieldValueByName(storeIdField, object))) { 57 | // Nếu khớp, trả về đối tượng object 58 | return object; 59 | } else { 60 | throw new ServiceException(ResultCode.USER_PERMISSION_ERROR); 61 | } 62 | default: 63 | throw new ServiceException(ResultCode.USER_PERMISSION_ERROR); 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/security/SecurityBean.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.security; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 6 | import org.springframework.web.cors.CorsConfiguration; 7 | import org.springframework.web.cors.CorsConfigurationSource; 8 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource; 9 | 10 | import java.util.Collections; 11 | 12 | /** 13 | * Bean Security 14 | */ 15 | @Configuration 16 | public class SecurityBean { 17 | 18 | @Bean 19 | public BCryptPasswordEncoder passwordEncoder() { 20 | return new BCryptPasswordEncoder(); 21 | } 22 | 23 | /** 24 | * Định nghĩa cấu hình chéo miền 25 | * 26 | * @return bean 27 | */ 28 | @Bean 29 | CorsConfigurationSource corsConfigurationSource() { 30 | // Khởi tạo một đối tượng UrlBasedCorsConfigurationSource, một lớp được sử dụng để cấu hình CORS dựa trên URL 31 | UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); 32 | // Khởi tạo một đối tượng CorsConfiguration, một lớp được sử dụng để xác định các thông số cấu hình CORS 33 | CorsConfiguration config = new CorsConfiguration(); 34 | // Cho phép gửi cookie trong các yêu cầu cross-origin 35 | config.setAllowCredentials(true); 36 | // Cho phép tất cả các nguồn gốc 37 | config.setAllowedOriginPatterns(Collections.singletonList(CorsConfiguration.ALL)); 38 | // Cho phép tất cả các header 39 | config.addAllowedHeader(CorsConfiguration.ALL); 40 | // Cho phép tất cả các phương thức HTTP 41 | config.addAllowedMethod(CorsConfiguration.ALL); 42 | // Đăng ký cấu hình CORS cho tất cả các URL 43 | source.registerCorsConfiguration("/**", config); 44 | // Trả về đối tượng CorsConfigurationSource 45 | return source; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/security/enums/PermissionEnum.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.security.enums; 2 | 3 | /** 4 | * Danh sách quyền hạn 5 | * 6 | * @author vantrang 7 | */ 8 | public enum PermissionEnum { 9 | 10 | /** 11 | * Quyền hạn siêu cấp, quyền xem 12 | */ 13 | SUPER, QUERY 14 | 15 | } 16 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/security/enums/SecurityEnum.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.security.enums; 2 | 3 | /** 4 | * Các hằng số liên quan đến bảo mật 5 | * 6 | * @author vantrang 7 | */ 8 | public enum SecurityEnum { 9 | 10 | /** 11 | * Tên tham số token trong header 12 | */ 13 | AUTHORIZATION_HEADER("accessToken"), 14 | 15 | /** 16 | * Tên trường lưu thông tin người dùng trong token JWT 17 | */ 18 | USER_CONTEXT_KEY("userContext"), 19 | 20 | /** 21 | * Khóa bí mật cho mã hóa và giải mã token JWT 22 | */ 23 | JWT_SECRET("secret"), 24 | 25 | /** 26 | * Tên header chứa UUID của người dùng 27 | */ 28 | UUID("uuid"), 29 | 30 | /** 31 | * Tên header hoặc tên trường trong token JWT chứa ID người mời 32 | */ 33 | INVITER("inviter"); 34 | 35 | String value; 36 | 37 | SecurityEnum(String value) { 38 | // Gán giá trị của chuỗi value cho thuộc tính value của enum 39 | this.value = value; 40 | } 41 | 42 | public String getValue() { 43 | return value; 44 | } 45 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/security/enums/UserEnums.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.security.enums; 2 | 3 | /** 4 | * Token Role Type 5 | * 6 | * @author vantrang 7 | * @since 2024/10/22 8 | */ 9 | public enum UserEnums { 10 | /** 11 | * Vai trò 12 | */ 13 | MEMBER("member"), 14 | STORE("store"), 15 | MANAGER("manager"), 16 | SYSTEM("system"); 17 | private final String role; 18 | 19 | UserEnums(String r) { 20 | this.role = r; 21 | } 22 | 23 | public String getRole() { 24 | return role; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/security/sensitive/SensitiveData.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.security.sensitive; 2 | 3 | import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; 4 | import com.fasterxml.jackson.databind.annotation.JsonSerialize; 5 | import com.myshop.common.security.sensitive.enums.SensitiveStrategy; 6 | 7 | import java.lang.annotation.ElementType; 8 | import java.lang.annotation.Retention; 9 | import java.lang.annotation.RetentionPolicy; 10 | import java.lang.annotation.Target; 11 | 12 | 13 | /** 14 | * Chú thích nhạy cảm 15 | */ 16 | @Retention(RetentionPolicy.RUNTIME) 17 | @Target(ElementType.FIELD) 18 | @JacksonAnnotationsInside 19 | @JsonSerialize(using = SensitiveJsonSerializer.class) 20 | public @interface SensitiveData { 21 | SensitiveStrategy strategy(); 22 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/security/sensitive/SensitiveJsonSerializer.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.security.sensitive; 2 | 3 | import com.fasterxml.jackson.core.JsonGenerator; 4 | import com.fasterxml.jackson.databind.BeanProperty; 5 | import com.fasterxml.jackson.databind.JsonMappingException; 6 | import com.fasterxml.jackson.databind.JsonSerializer; 7 | import com.fasterxml.jackson.databind.SerializerProvider; 8 | import com.fasterxml.jackson.databind.ser.ContextualSerializer; 9 | import com.myshop.common.properties.SystemProperties; 10 | import com.myshop.common.security.AuthUser; 11 | import com.myshop.common.security.context.UserContext; 12 | import com.myshop.common.security.enums.UserEnums; 13 | import com.myshop.common.security.sensitive.enums.SensitiveStrategy; 14 | import org.springframework.beans.BeansException; 15 | import org.springframework.context.ApplicationContext; 16 | import org.springframework.context.ApplicationContextAware; 17 | 18 | import java.io.IOException; 19 | import java.util.Objects; 20 | 21 | /** 22 | * Lọc thông tin nhạy cảm khi serialize 23 | */ 24 | public class SensitiveJsonSerializer extends JsonSerializer implements ContextualSerializer, ApplicationContextAware { 25 | 26 | private SensitiveStrategy sensitiveStrategy; 27 | 28 | // Cấu hình hệ thống 29 | private SystemProperties systemProperties; 30 | 31 | @Override 32 | public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException { 33 | // Xử lý serialize cho trường 34 | gen.writeString(sensitiveStrategy.maskingFunction().apply(value)); 35 | } 36 | 37 | @Override 38 | public JsonSerializer createContextual(SerializerProvider provider, BeanProperty property) throws JsonMappingException { 39 | 40 | // Kiểm tra xem có cần xử lý ẩn thông tin hay không 41 | if (desensitization()) { 42 | // Lấy enum nhạy cảm 43 | SensitiveData sensitiveAnnotation = property.getAnnotation(SensitiveData.class); 44 | // Nếu có chú thích nhạy cảm, áp dụng quy tắc ẩn thông tin 45 | if (Objects.nonNull(sensitiveAnnotation) && Objects.equals(String.class, property.getType().getRawClass())) { 46 | this.sensitiveStrategy = sensitiveAnnotation.strategy(); 47 | return this; 48 | } 49 | } 50 | return provider.findValueSerializer(property.getType(), property); 51 | 52 | } 53 | 54 | @Override 55 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 56 | systemProperties = applicationContext.getBean(SystemProperties.class); 57 | } 58 | 59 | /** 60 | * Kiểm tra xem có cần xử lý ẩn thông tin hay không 61 | * 62 | * @return 63 | */ 64 | private boolean desensitization() { 65 | 66 | // Người dùng hiện tại 67 | AuthUser currentAuthUser = UserContext.getCurrentUser(); 68 | // Mặc định là không ẩn thông tin 69 | if (currentAuthUser == null) { 70 | return false; 71 | } 72 | 73 | // Nếu là cửa hàng 74 | if (currentAuthUser.getRole().equals(UserEnums.STORE)) { 75 | // Cửa hàng cần ẩn thông tin, thì xử lý ẩn thông tin 76 | return systemProperties.getDataMaskingLevel() == 2; 77 | } 78 | 79 | 80 | // Nếu là quản trị viên 81 | if (currentAuthUser.getRole().equals(UserEnums.MANAGER)) { 82 | // Quản trị viên cần ẩn thông tin, thì xử lý ẩn thông tin 83 | return systemProperties.getDataMaskingLevel() >= 1; 84 | } 85 | 86 | return false; 87 | } 88 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/security/sensitive/enums/SensitiveStrategy.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.security.sensitive.enums; 2 | 3 | import java.util.function.Function; 4 | 5 | /** 6 | * Enum Sensitive Strategy 7 | */ 8 | 9 | public enum SensitiveStrategy { 10 | /** 11 | * Chiến lược nhạy cảm cho Username. 12 | */ 13 | USERNAME(s -> s.replaceAll("(\\S)\\S(\\S*)", "$1*$2")), 14 | /** 15 | * Loại nhạy cảm cho chứng minh nhân dân. 16 | */ 17 | ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\w{4})", "$1****$2")), 18 | /** 19 | * Loại nhạy cảm cho số điện thoại. 20 | */ 21 | PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")), 22 | /** 23 | * Loại nhạy cảm cho email. 24 | */ 25 | EMAIL(s -> s.replaceAll("(^\\w)[^@]*(@.*$)", "$1****$2")), 26 | /** 27 | * Loại nhạy cảm cho địa chỉ. 28 | */ 29 | ADDRESS(s -> s.replaceAll("(\\S{3})\\S{2}(\\S*)\\S{2}", "$1****$2****")); 30 | 31 | 32 | private final Function maskingFunction; 33 | 34 | SensitiveStrategy(Function maskingFunction) { 35 | this.maskingFunction = maskingFunction; 36 | } 37 | 38 | public Function maskingFunction() { 39 | return maskingFunction; 40 | } 41 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/security/token/SecretKeyUtil.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.security.token; 2 | 3 | import io.jsonwebtoken.io.Decoders; 4 | import io.jsonwebtoken.security.Keys; 5 | import org.apache.commons.codec.binary.Base64; 6 | 7 | import javax.crypto.SecretKey; 8 | 9 | /** 10 | * Secret key util 11 | * 12 | * @author vantrang 13 | */ 14 | public class SecretKeyUtil { 15 | public static SecretKey generalKey() { 16 | // tuỳ chỉnh 17 | byte[] encodedKey = Base64.decodeBase64("cuAihCz53DZRjZwbsGcZJ2sajdkakqasAi6At+T142uphtJMsk7iQ="); 18 | SecretKey key = Keys.hmacShaKeyFor(encodedKey); 19 | return key; 20 | } 21 | 22 | public static SecretKey generalKeyByDecoders() { 23 | return Keys.hmacShaKeyFor(Decoders.BASE64.decode("cuAihCz53DZRjZwbsGcZJ2sajdkakqasAi6At+T142uphtJMsk7iQ=")); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/security/token/Token.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.security.token; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * Lớp thực thể Token 7 | * 8 | * @author vantrang 9 | */ 10 | @Data 11 | public class Token { 12 | /** 13 | * Access token 14 | */ 15 | private String accessToken; 16 | 17 | /** 18 | * Refresh token 19 | */ 20 | private String refreshToken; 21 | 22 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/security/token/base/TokenGeneratorBase.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.security.token.base; 2 | 3 | import com.myshop.common.security.enums.UserEnums; 4 | import com.myshop.common.security.token.Token; 5 | 6 | /** 7 | * AbstractToken 8 | * Lớp trừu tượng token, định nghĩa lớp tạo token 9 | * 10 | * @author vantrang 11 | */ 12 | public abstract class TokenGeneratorBase { 13 | 14 | /** 15 | * Tạo token 16 | * 17 | * @param user Tên người dùng 18 | * @param lTerm Có thời hạn dài hay không 19 | * @return Đối tượng TOKEN 20 | */ 21 | public abstract Token createToken(T user, Boolean lTerm); 22 | 23 | /** 24 | * Làm mới token 25 | * 26 | * @param reToken Token làm mới 27 | * @return token 28 | */ 29 | public abstract Token refreshToken(String reToken); 30 | 31 | /** 32 | * Vai trò mặc định 33 | */ 34 | public UserEnums role = UserEnums.MANAGER; 35 | 36 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/thread/ThreadPoolConfig.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.thread; 2 | 3 | import com.myshop.common.properties.ThreadPoolProperties; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.scheduling.annotation.AsyncConfigurer; 7 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; 8 | 9 | import java.util.concurrent.Executor; 10 | 11 | /** 12 | * Cấu hình đa luồng 13 | */ 14 | @Configuration 15 | public class ThreadPoolConfig implements AsyncConfigurer { 16 | 17 | 18 | @Autowired 19 | private ThreadPoolProperties threadPoolProperties; 20 | 21 | @Override 22 | public Executor getAsyncExecutor() { 23 | ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor(); 24 | //Số lượng luồng cốt lõi, mặc định là 5 25 | threadPool.setCorePoolSize(threadPoolProperties.getCorePoolSize()); 26 | //Số lượng luồng tối đa, mặc định là 10 27 | threadPool.setMaxPoolSize(threadPoolProperties.getMaxPoolSize()); 28 | //Độ dài tối đa của hàng đợi, thường cần thiết lập giá trị đủ lớn 29 | threadPool.setQueueCapacity(threadPoolProperties.getQueueCapacity()); 30 | //Thời gian chờ tối đa của luồng trong bộ nhớ cache, mặc định là 60s 31 | threadPool.setKeepAliveSeconds(threadPoolProperties.getKeepAliveSeconds()); 32 | //Cho phép đóng luồng hết thời gian chờ 33 | threadPool.setAllowCoreThreadTimeOut(threadPoolProperties.getAllowCoreThreadTimeOut()); 34 | threadPool.initialize(); 35 | return threadPool; 36 | } 37 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/utils/CommonUtil.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.utils; 2 | 3 | import java.util.UUID; 4 | import java.util.concurrent.ThreadLocalRandom; 5 | 6 | /** 7 | * Công cụ chung 8 | */ 9 | public class CommonUtil { 10 | 11 | public static final String NUMBER_DIGITS = "0123456789"; 12 | 13 | /** 14 | * Đổi tên bằng UUID 15 | * 16 | * @param fileName Tên tệp 17 | * @return Tên đã được định dạng 18 | */ 19 | public static String generateUniqueFileName(String fileName) { 20 | String extension = fileName.substring(fileName.lastIndexOf(".")); 21 | return UUID.randomUUID().toString().replace("-", "") + extension; 22 | } 23 | 24 | 25 | /** 26 | * Tạo số ngẫu nhiên 6 chữ số 27 | */ 28 | public static String getRandomNum() { 29 | StringBuilder sb = new StringBuilder(6); 30 | for (int i = 0; i < 6; i++) { 31 | int num = ThreadLocalRandom.current().nextInt(NUMBER_DIGITS.length()); 32 | sb.append(NUMBER_DIGITS.charAt(num)); 33 | } 34 | return sb.toString(); 35 | } 36 | 37 | /** 38 | * Lấy chuỗi đặc biệt + 6 chữ số ngẫu nhiên 39 | * 40 | * @return 41 | */ 42 | public static String generateSpecialString(String str) { 43 | return str + getRandomNum(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/utils/CookieUtil.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.utils; 2 | 3 | import jakarta.servlet.http.Cookie; 4 | import jakarta.servlet.http.HttpServletRequest; 5 | import jakarta.servlet.http.HttpServletResponse; 6 | import lombok.extern.slf4j.Slf4j; 7 | 8 | 9 | /** 10 | * Công cụ Cookie 11 | */ 12 | @Slf4j 13 | public class CookieUtil { 14 | 15 | 16 | /** 17 | * Thêm cookie 18 | * 19 | * @param cookieKey Giá trị khóa 20 | * @param cookieValue Giá trị tương ứng 21 | * @param maxAge Thời gian hiệu lực của cookie 22 | * @param response Phản hồi 23 | */ 24 | public static void addCookie(String cookieKey, String cookieValue, Integer maxAge, HttpServletResponse response) { 25 | try { 26 | Cookie cookie = new Cookie(cookieKey, cookieValue); 27 | cookie.setMaxAge(maxAge); 28 | cookie.setPath("/"); 29 | response.addCookie(cookie); 30 | } catch (Exception e) { 31 | log.error("Thêm cookie lỗi", e); 32 | } 33 | } 34 | 35 | /** 36 | * Xóa cookie 37 | * 38 | * @param cookieKey Giá trị khóa 39 | * @param response Phản hồi 40 | */ 41 | public static void delCookie(String cookieKey, HttpServletResponse response) { 42 | try { 43 | Cookie cookie = new Cookie(cookieKey, ""); 44 | cookie.setMaxAge(0); 45 | response.addCookie(cookie); 46 | } catch (Exception e) { 47 | log.error("Xóa cookie lỗi", e); 48 | } 49 | } 50 | 51 | /** 52 | * Lấy cookie 53 | * 54 | * @param cookieKey Giá trị khóa 55 | * @param request Yêu cầu 56 | * @return Giá trị cookie 57 | */ 58 | public static String getCookie(String cookieKey, HttpServletRequest request) { 59 | try { 60 | if (request.getCookies() == null) { 61 | return null; 62 | } 63 | for (int i = 0; i < request.getCookies().length; i++) { 64 | if (request.getCookies()[i].getName().equals(cookieKey)) { 65 | return request.getCookies()[i].getValue(); 66 | } 67 | } 68 | } catch (Exception e) { 69 | log.error("Lấy cookie lỗi", e); 70 | } 71 | return null; 72 | } 73 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/validation/EnumValue.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.validation; 2 | 3 | import com.myshop.common.validation.impl.EnumValueChecker; 4 | import jakarta.validation.Constraint; 5 | import jakarta.validation.Payload; 6 | 7 | import java.lang.annotation.Documented; 8 | import java.lang.annotation.Retention; 9 | import java.lang.annotation.Target; 10 | 11 | import static java.lang.annotation.ElementType.*; 12 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 13 | 14 | /** 15 | * Chú thích xác thực giá trị enum 16 | */ 17 | @Documented 18 | @Retention(RUNTIME) 19 | @Constraint(validatedBy = {EnumValueChecker.class}) 20 | @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER}) 21 | public @interface EnumValue { 22 | 23 | String message() default "Phải là giá trị đã chỉ định"; 24 | 25 | String[] strValues() default {}; 26 | 27 | int[] intValues() default {}; 28 | 29 | // groups 30 | Class[] groups() default {}; 31 | 32 | // payload 33 | Class[] payload() default {}; 34 | 35 | 36 | @Target({FIELD, METHOD, PARAMETER, ANNOTATION_TYPE}) 37 | @Retention(RUNTIME) 38 | @Documented 39 | @interface List { 40 | EnumValue[] value(); 41 | } 42 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/validation/Mobile.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.validation; 2 | 3 | import com.myshop.common.validation.impl.MobileValidator; 4 | import jakarta.validation.Constraint; 5 | import jakarta.validation.Payload; 6 | 7 | import java.lang.annotation.Documented; 8 | import java.lang.annotation.Retention; 9 | import java.lang.annotation.Target; 10 | 11 | import static java.lang.annotation.ElementType.*; 12 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 13 | 14 | /** 15 | * Chú thích xác thực số điện thoại 16 | */ 17 | @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER}) 18 | @Retention(RUNTIME) 19 | @Documented 20 | @Constraint(validatedBy = {MobileValidator.class}) 21 | public @interface Mobile { 22 | 23 | String regexp() default ""; 24 | 25 | String message() default "Số điện thoại không hợp lệ"; 26 | 27 | Class[] groups() default {}; 28 | 29 | Class[] payload() default {}; 30 | } 31 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/validation/impl/EnumValueChecker.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.validation.impl; 2 | 3 | 4 | import com.myshop.common.validation.EnumValue; 5 | import jakarta.validation.ConstraintValidator; 6 | import jakarta.validation.ConstraintValidatorContext; 7 | 8 | /** 9 | * Xác thực giá trị enum 10 | */ 11 | public class EnumValueChecker implements ConstraintValidator { 12 | 13 | private String[] stringValues; 14 | private int[] integerValues; 15 | 16 | @Override 17 | public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) { 18 | if (value instanceof String) { 19 | for (String s : stringValues) { 20 | if (s.equals(value)) { 21 | return true; 22 | } 23 | } 24 | } else if (value instanceof Integer) { 25 | for (int s : integerValues) { 26 | if (s == ((Integer) value).intValue()) { 27 | return true; 28 | } 29 | } 30 | } 31 | return false; 32 | } 33 | 34 | @Override 35 | public void initialize(EnumValue constraintAnnotation) { 36 | stringValues = constraintAnnotation.strValues(); 37 | integerValues = constraintAnnotation.intValues(); 38 | } 39 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/validation/impl/MobileValidator.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.validation.impl; 2 | 3 | import com.myshop.common.validation.Mobile; 4 | import jakarta.validation.ConstraintValidator; 5 | import jakarta.validation.ConstraintValidatorContext; 6 | 7 | import java.util.regex.Matcher; 8 | import java.util.regex.Pattern; 9 | 10 | /** 11 | * Xác thực số điện thoại 12 | * Hỗ trợ xác thực cả số di động và số điện thoại cố định 13 | */ 14 | public class MobileValidator implements ConstraintValidator { 15 | 16 | private static final Pattern MOBILE_PHONE_PATTERN = Pattern.compile("^0?(13[0-9]|14[0-9]|15[0-9]|16[0-9]|17[0-9]|18[0-9]|19[0-9])[0-9]{8}$"); 17 | private static final Pattern AREA_PHONE_PATTERN = Pattern.compile("0\\d{2,3}[-]?\\d{7,8}|0\\d{2,3}\\s?\\d{7,8}|13[0-9]\\d{8}|15[1089]\\d{8}|16[2-7]\\d{8}|17[6-8]\\d{8}|18[0-9]\\d{8}"); 18 | private static final Pattern SHORT_PHONE_PATTERN = Pattern.compile("^[1-9]{1}[0-9]{5,8}$"); 19 | 20 | @Override 21 | public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) { 22 | Matcher matcher = null; 23 | // Xác thực số di động 24 | if (value.length() == 11) { 25 | matcher = MOBILE_PHONE_PATTERN.matcher(value); 26 | // Xác thực số điện thoại cố định có mã vùng 27 | } else if (value.length() > 9) { 28 | matcher = AREA_PHONE_PATTERN.matcher(value); 29 | // Xác thực số điện thoại cố định không có mã vùng 30 | } else { 31 | matcher = SHORT_PHONE_PATTERN.matcher(value); 32 | } 33 | return matcher.matches(); 34 | } 35 | 36 | 37 | @Override 38 | public void initialize(Mobile constraint) { 39 | // Không cần thực hiện gì trong phương thức này 40 | } 41 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/vo/PageVO/PageVO.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.vo.PageVO; 2 | 3 | import cn.hutool.core.text.CharSequenceUtil; 4 | import com.myshop.common.utils.StringUtils; 5 | import io.swagger.annotations.ApiModelProperty; 6 | import lombok.Data; 7 | 8 | import java.io.Serializable; 9 | 10 | /** 11 | * Tham số truy vấn 12 | */ 13 | @Data 14 | public class PageVO implements Serializable { 15 | 16 | private static final long serialVersionUID = 1L; 17 | 18 | @ApiModelProperty(value = "Số trang") 19 | private Integer currentPage = 1; 20 | 21 | @ApiModelProperty(value = "Số lượng mỗi trang") 22 | private Integer pageLimit = 10; 23 | 24 | @ApiModelProperty(value = "Trường sắp xếp") 25 | private String sortBy; 26 | 27 | @ApiModelProperty(value = "Cách sắp xếp asc/desc") 28 | private String sortOrder; 29 | 30 | @ApiModelProperty(value = "Cần chuyển đổi camel sang snake", notes = "Thường không xử lý, nếu cơ sở dữ liệu là snake, thì phần này cần được xử lý.") 31 | private Boolean convertCamelToSnake; 32 | 33 | public String getSortField() { 34 | if (CharSequenceUtil.isNotEmpty(sortBy)) { 35 | if (convertCamelToSnake == null || Boolean.FALSE.equals(convertCamelToSnake)) { 36 | return StringUtils.camel2Underline(sortBy); 37 | } else { 38 | return sortBy; 39 | } 40 | } 41 | return sortBy; 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/common/vo/ResultMessage.java: -------------------------------------------------------------------------------- 1 | package com.myshop.common.vo; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * VO tương tác giữa frontend và backend 9 | * 10 | * @author vantrang 11 | */ 12 | @Data 13 | public class ResultMessage implements Serializable { 14 | 15 | private static final long serialVersionUID = 1L; 16 | 17 | /** 18 | * Cờ thành công 19 | */ 20 | private boolean success; 21 | 22 | /** 23 | * Thông báo 24 | */ 25 | private String message; 26 | 27 | /** 28 | * Mã trả về 29 | */ 30 | private Integer code; 31 | 32 | /** 33 | * Dấu thời gian 34 | */ 35 | private long timestamp = System.currentTimeMillis(); 36 | 37 | /** 38 | * Đối tượng kết quả 39 | */ 40 | private T result; 41 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/member/entity/dos/Employee.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.member.entity.dos; 2 | 3 | import cn.hutool.core.text.CharSequenceUtil; 4 | import com.baomidou.mybatisplus.annotation.TableName; 5 | import com.myshop.modules.member.entity.dto.EmployeeAddDTO; 6 | import com.myshop.modules.store.entity.dos.Store; 7 | import com.myshop.orm.BaseEntity; 8 | import io.swagger.annotations.ApiModel; 9 | import io.swagger.annotations.ApiModelProperty; 10 | import lombok.AllArgsConstructor; 11 | import lombok.Data; 12 | import lombok.NoArgsConstructor; 13 | 14 | /** 15 | * Mô hình nhân viên 16 | */ 17 | @Data 18 | @TableName("myshop_employee") 19 | @ApiModel(value = "Nhân viên") 20 | @NoArgsConstructor 21 | @AllArgsConstructor 22 | public class Employee extends BaseEntity { 23 | 24 | private static final long serialVersionUID = 1L; 25 | 26 | @ApiModelProperty(value = "Tên nhân viên") 27 | private String name; 28 | 29 | @ApiModelProperty(value = "ID thành viên") 30 | private String memberID; 31 | 32 | @ApiModelProperty(value = "ID cửa hàng") 33 | private String storeID; 34 | 35 | @ApiModelProperty(value = "ID bộ phận") 36 | private String departmentID; 37 | 38 | @ApiModelProperty(value = "Bộ sưu tập ID vai trò") 39 | private String roleIDs; 40 | 41 | @ApiModelProperty(value = "Có phải là chủ cửa hàng hay không", hidden = true) 42 | private Boolean isShopkeeper = false; 43 | 44 | @ApiModelProperty(value = "Có phải là quản trị viên hay không", hidden = true) 45 | private Boolean isAdmin = false; 46 | 47 | @ApiModelProperty(value = "Trạng thái Mặc định true bình thường false vô hiệu hóa") 48 | private Boolean isEnabled = true; 49 | 50 | /** 51 | * Xây dựng nhân viên 52 | * 53 | * @param employeeAddDTO 54 | */ 55 | public Employee(EmployeeAddDTO employeeAddDTO) { 56 | if (employeeAddDTO.getRoles() != null && !employeeAddDTO.getRoles().isEmpty()) { 57 | this.roleIDs = CharSequenceUtil.join(",", employeeAddDTO.getRoles()); 58 | } 59 | this.memberID = employeeAddDTO.getMemberId(); 60 | this.departmentID = employeeAddDTO.getDepartmentId(); 61 | this.storeID = employeeAddDTO.getStoreId(); 62 | this.name = employeeAddDTO.getUsername(); 63 | 64 | } 65 | 66 | 67 | public Employee(Store store) { 68 | this.memberID = store.getMemberId(); 69 | this.storeID = store.getId(); 70 | this.name = store.getMemberName(); 71 | this.setIsShopkeeper(true); 72 | this.setIsAdmin(true); 73 | this.setIsEnabled(true); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/member/entity/dos/StoreMenu.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.member.entity.dos; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import com.myshop.orm.BaseEntity; 5 | import io.swagger.annotations.ApiModel; 6 | import io.swagger.annotations.ApiModelProperty; 7 | import lombok.Data; 8 | 9 | /** 10 | * Quyền hạn menu 11 | */ 12 | @Data 13 | @TableName("myshop_store_menu") 14 | @ApiModel(value = "Quyền hạn menu của cửa hàng") 15 | public class StoreMenu extends BaseEntity { 16 | 17 | private static final long serialVersionUID = 7050754476203495207L; 18 | 19 | 20 | @ApiModelProperty(value = "Tiêu đề menu") 21 | private String title; 22 | 23 | @ApiModelProperty(value = "Tên định tuyến") 24 | private String name; 25 | 26 | @ApiModelProperty(value = "Đường dẫn") 27 | private String path; 28 | 29 | @ApiModelProperty(value = "Cấp bậc menu") 30 | private Integer level; 31 | 32 | @ApiModelProperty(value = "Tệp đường dẫn frontend") 33 | private String frontendRoute; 34 | 35 | @ApiModelProperty(value = "ID cha") 36 | private String parentId = "0"; 37 | 38 | @ApiModelProperty(value = "Giá trị sắp xếp") 39 | private Double sortOrder; 40 | 41 | @ApiModelProperty(value = "URL quyền hạn, * là ký hiệu đại diện, phân cách bằng dấu phẩy") 42 | private String permission; 43 | 44 | 45 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/member/entity/dos/StoreRoleMenu.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.member.entity.dos; 2 | 3 | 4 | import com.baomidou.mybatisplus.annotation.TableName; 5 | import com.myshop.orm.BaseEntity; 6 | import io.swagger.annotations.ApiModel; 7 | import io.swagger.annotations.ApiModelProperty; 8 | import lombok.Data; 9 | 10 | 11 | /** 12 | * Liên kết quyền hạn của vai trò 13 | */ 14 | @Data 15 | @TableName("myshop_store_role_menu") 16 | @ApiModel(value = "Quyền hạn của vai trò cửa hàng") 17 | public class StoreRoleMenu extends BaseEntity { 18 | 19 | private static final long serialVersionUID = -4680260093546996026L; 20 | 21 | @ApiModelProperty(value = "ID của vai trò") 22 | private String roleId; 23 | 24 | @ApiModelProperty(value = "Menu") 25 | private String menuId; 26 | 27 | @ApiModelProperty(value = "ID của cửa hàng") 28 | private String storeId; 29 | 30 | @ApiModelProperty(value = "Có quyền thao tác dữ liệu hay không, nếu không thì chỉ có quyền xem") 31 | private Boolean isSuper; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/member/entity/dto/EmployeeAddDTO.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.member.entity.dto; 2 | 3 | import com.myshop.common.security.sensitive.SensitiveData; 4 | import com.myshop.common.security.sensitive.enums.SensitiveStrategy; 5 | import io.swagger.annotations.ApiModelProperty; 6 | import jakarta.validation.constraints.NotEmpty; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import org.hibernate.validator.constraints.Length; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * DTO của nhân viên 15 | */ 16 | @Data 17 | @NoArgsConstructor 18 | public class EmployeeAddDTO { 19 | 20 | private static final long serialVersionUID = 1L; 21 | 22 | @ApiModelProperty(value = "Tên người dùng thành viên") 23 | @NotEmpty(message = "Tên người dùng thành viên không được để trống") 24 | @Length(max = 30, message = "Tên người dùng thành viên không được vượt quá 30 ký tự") 25 | private String username; 26 | 27 | @ApiModelProperty(value = "Mật khẩu thành viên") 28 | @NotEmpty(message = "Mật khẩu thành viên không được để trống") 29 | private String password; 30 | 31 | @NotEmpty(message = "Số điện thoại không được để trống") 32 | @ApiModelProperty(value = "Số điện thoại", required = true) 33 | @SensitiveData(strategy = SensitiveStrategy.PHONE) 34 | private String mobile; 35 | 36 | @ApiModelProperty(value = "ID bộ phận") 37 | private String departmentId; 38 | 39 | @ApiModelProperty(value = "Có phải là quản trị viên siêu cấp hay không Quản trị viên siêu cấp/Quản trị viên thông thường") 40 | private Boolean isSuper = false; 41 | 42 | @ApiModelProperty(value = "Vai trò") 43 | private List roles; 44 | 45 | @ApiModelProperty(value = "ID thành viên", required = true) 46 | private String memberId; 47 | 48 | @ApiModelProperty(value = "Có phải là chủ cửa hàng hay không", hidden = true) 49 | private Boolean shopkeeper = false; 50 | 51 | @ApiModelProperty(value = "ID cửa hàng", hidden = true) 52 | private String storeId; 53 | 54 | 55 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/member/entity/vo/StoreMenuUserVO.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.member.entity.vo; 2 | 3 | import com.myshop.modules.member.entity.dos.StoreMenu; 4 | import lombok.Data; 5 | 6 | /** 7 | * StoreUserMenuVO 8 | */ 9 | @Data 10 | public class StoreMenuUserVO extends StoreMenu { 11 | 12 | private static final long serialVersionUID = -7478970595109016162L; 13 | 14 | /** 15 | * Là siêu quản trị viên hay không 16 | */ 17 | private Boolean isSuper; 18 | 19 | public Boolean getSuper() { 20 | return isSuper != null && isSuper; 21 | } 22 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/member/mapper/EmployeeMapper.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.member.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.myshop.modules.member.entity.dos.Employee; 5 | 6 | public interface EmployeeMapper extends BaseMapper { 7 | } 8 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/member/mapper/StoreMenuMapper.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.member.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.myshop.modules.member.entity.dos.StoreMenu; 5 | import com.myshop.modules.member.entity.vo.StoreMenuUserVO; 6 | 7 | import java.util.List; 8 | 9 | public interface StoreMenuMapper extends BaseMapper { 10 | 11 | 12 | /** 13 | * Lấy quyền hạn menu dựa trên người dùng 14 | * 15 | * @param userId ID người dùng 16 | * @return Danh sách StoreMenuUserVO của người dùng 17 | */ 18 | List getUserRoleMenu(String userId); 19 | } 20 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/member/mapper/StoreRoleMenuMapper.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.member.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.myshop.modules.member.entity.dos.StoreRoleMenu; 5 | 6 | public interface StoreRoleMenuMapper extends BaseMapper { 7 | } 8 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/member/service/EmployeeService.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.member.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.myshop.modules.member.entity.dos.Employee; 5 | 6 | public interface EmployeeService extends IService { 7 | /** 8 | * Lấy thông tin nhân viên dựa trên ID thành viên 9 | * 10 | * @param memberId ID thành viên 11 | * @return 12 | */ 13 | Employee getEmployeeByMemberId(String memberId); 14 | } 15 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/member/service/MemberService.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.member.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.myshop.common.security.token.Token; 5 | import com.myshop.modules.member.entity.dos.Member; 6 | 7 | public interface MemberService extends IService { 8 | 9 | /** 10 | * Đăng nhập: Tên đăng nhập, mật khẩu 11 | * 12 | * @param username Tên đăng nhập 13 | * @param password Mật khẩu 14 | * @return token 15 | */ 16 | Token login(String username, String password); 17 | } 18 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/member/service/StoreMenuService.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.member.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.myshop.modules.member.entity.dos.StoreMenu; 5 | import com.myshop.modules.member.entity.vo.StoreMenuUserVO; 6 | import org.springframework.cache.annotation.CacheConfig; 7 | 8 | import java.util.List; 9 | 10 | @CacheConfig(cacheNames = "{store_menu_data}") 11 | public interface StoreMenuService extends IService { 12 | 13 | List getUserRoleMenu(String employeeId); 14 | } 15 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/member/service/StoreRoleMenuService.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.member.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.myshop.modules.member.entity.dos.StoreRoleMenu; 5 | import com.myshop.modules.member.entity.vo.StoreMenuUserVO; 6 | 7 | import java.util.List; 8 | 9 | public interface StoreRoleMenuService extends IService { 10 | 11 | 12 | /** 13 | * Lấy danh sách quyền hạn menu chi tiết dựa trên tập hợp vai trò 14 | * 15 | * @param clerkId ID nhân viên 16 | * @param memberId ID thành viên 17 | * @return 18 | */ 19 | List findAllMenu(String clerkId, String memberId); 20 | } 21 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/member/service/StoreRoleMenuServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.member.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.myshop.cache.Cache; 5 | import com.myshop.cache.CachePrefix; 6 | import com.myshop.modules.member.entity.dos.StoreRoleMenu; 7 | import com.myshop.modules.member.entity.vo.StoreMenuUserVO; 8 | import com.myshop.modules.member.mapper.StoreRoleMenuMapper; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Service; 12 | import org.springframework.transaction.annotation.Transactional; 13 | 14 | import java.util.List; 15 | 16 | /** 17 | * Triển khai lớp nghiệp vụ của menu vai trò 18 | */ 19 | @Slf4j 20 | @Service 21 | @Transactional(rollbackFor = Exception.class) 22 | public class StoreRoleMenuServiceImpl extends ServiceImpl implements StoreRoleMenuService { 23 | 24 | @Autowired 25 | private StoreMenuService storeMenuService; 26 | 27 | @Autowired 28 | private Cache cache; 29 | 30 | @Override 31 | public List findAllMenu(String employeeId, String memberId) { 32 | String userMenuCacheKey = CachePrefix.STORE_MENU_USER + memberId; 33 | List menuList = (List) cache.get(userMenuCacheKey); 34 | if (menuList == null || menuList.isEmpty()) { 35 | menuList = storeMenuService.getUserRoleMenu(employeeId); 36 | cache.put(userMenuCacheKey, menuList); 37 | } 38 | return menuList; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/member/serviceimpl/EmployeeServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.member.serviceimpl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import com.myshop.modules.member.entity.dos.Employee; 6 | import com.myshop.modules.member.mapper.EmployeeMapper; 7 | import com.myshop.modules.member.service.EmployeeService; 8 | import org.springframework.stereotype.Service; 9 | import org.springframework.transaction.annotation.Transactional; 10 | 11 | @Service 12 | @Transactional(rollbackFor = Exception.class) 13 | public class EmployeeServiceImpl extends ServiceImpl implements EmployeeService { 14 | 15 | @Override 16 | public Employee getEmployeeByMemberId(String memberId) { 17 | return this.getOne(new QueryWrapper().eq("member_id", memberId)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/member/serviceimpl/StoreMenuServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.member.serviceimpl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.myshop.modules.member.entity.dos.StoreMenu; 5 | import com.myshop.modules.member.entity.vo.StoreMenuUserVO; 6 | import com.myshop.modules.member.mapper.StoreMenuMapper; 7 | import com.myshop.modules.member.service.StoreMenuService; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.stereotype.Service; 10 | 11 | import java.util.List; 12 | 13 | @Slf4j 14 | @Service 15 | public class StoreMenuServiceImpl extends ServiceImpl implements StoreMenuService { 16 | @Override 17 | public List getUserRoleMenu(String employeeId) { 18 | return this.baseMapper.getUserRoleMenu(employeeId); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/member/token/MemberTokenProvider.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.member.token; 2 | 3 | import com.myshop.common.context.RequestScopeContext; 4 | import com.myshop.common.enums.ClientType; 5 | import com.myshop.common.security.AuthUser; 6 | import com.myshop.common.security.enums.UserEnums; 7 | import com.myshop.common.security.token.JwtTokenUtil; 8 | import com.myshop.common.security.token.Token; 9 | import com.myshop.common.security.token.base.TokenGeneratorBase; 10 | import com.myshop.modules.member.entity.dos.Member; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.stereotype.Component; 13 | 14 | import java.util.Date; 15 | 16 | 17 | @Component 18 | public class MemberTokenProvider extends TokenGeneratorBase { 19 | 20 | @Autowired 21 | private JwtTokenUtil jwtTokenUtil; 22 | 23 | @Override 24 | public Token createToken(Member member, Boolean longTerm) { 25 | 26 | ClientType clientType; 27 | try { 28 | // Lấy loại client 29 | String getClientType = RequestScopeContext.getHttpRequest().getHeader("clientType"); 30 | // Nếu loại client rỗng, mặc định là PC, khi đăng nhập bằng bên thứ ba trên PC sẽ không truyền tham số này 31 | if (getClientType == null) { 32 | clientType = ClientType.PC; 33 | } else { 34 | clientType = ClientType.valueOf(getClientType); 35 | } 36 | } catch (Exception e) { 37 | clientType = ClientType.UNKNOWN; 38 | } 39 | // Ghi lại thời gian đăng nhập cuối cùng và loại client 40 | member.setLastLoginDate(new Date()); 41 | member.setClientType(clientType.name()); 42 | 43 | //TODO: trien mq de goi thong tin user khi login de ghi lai log 44 | 45 | AuthUser user = AuthUser.builder().role(UserEnums.MEMBER).username(member.getUsername()).face(member.getFace()).id(member.getId()).nickName(member.getNickName()).longTerm(longTerm).build(); 46 | // Tạo token khi đăng nhập thành công 47 | return jwtTokenUtil.createToken(user); 48 | } 49 | 50 | @Override 51 | public Token refreshToken(String refreshToken) { 52 | return jwtTokenUtil.refreshToken(refreshToken); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/permission/entity/dos/AdminUser.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.permission.entity.dos; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import com.myshop.orm.BaseEntity; 5 | import io.swagger.annotations.ApiModel; 6 | import io.swagger.annotations.ApiModelProperty; 7 | import lombok.Data; 8 | import org.hibernate.validator.constraints.Length; 9 | 10 | /** 11 | * Lớp Quản trị viên 12 | */ 13 | @Data 14 | @TableName("myshop_admin_user") 15 | @ApiModel(value = "Quản trị viên") 16 | public class AdminUser extends BaseEntity { 17 | 18 | private static final long serialVersionUID = 2918352800205024873L; 19 | 20 | @ApiModelProperty(value = "Tên đăng nhập") // Swagger annotation để mô tả trường 21 | @Length(max = 20, message = "Tên đăng nhập không được vượt quá 20 ký tự") 22 | // Hibernate Validator annotation để kiểm tra độ dài 23 | private String username; 24 | 25 | @ApiModelProperty(value = "Mật khẩu") 26 | private String password; 27 | 28 | @ApiModelProperty(value = "Biệt danh") 29 | @Length(max = 10, message = "Biệt danh không được vượt quá 10 ký tự") 30 | private String nickName; 31 | 32 | @ApiModelProperty(value = "Số điện thoại") 33 | @Length(max = 11, message = "Số điện thoại không được vượt quá 11 ký tự") 34 | private String mobile; 35 | 36 | @ApiModelProperty(value = "Email") 37 | @Length(max = 100, message = "Email không được vượt quá 100 ký tự") 38 | private String email; 39 | 40 | @ApiModelProperty(value = "Ảnh đại diện") 41 | private String avatar = "https://i.loli.net/2020/11/19/LyN6JF7zZRskdIe.png"; 42 | 43 | @ApiModelProperty(value = "Là super admin hay không (Super admin/Quản trị viên)") 44 | private Boolean isSuper = false; // Giá trị mặc định 45 | 46 | @ApiModelProperty(value = "Trạng thái (true: hoạt động, false: bị khóa)") 47 | private Boolean status = true; // Giá trị mặc định 48 | 49 | @ApiModelProperty(value = "Mô tả/Chi tiết/Ghi chú") 50 | private String description; 51 | 52 | @ApiModelProperty(value = "ID phòng ban") 53 | private String departmentId; 54 | 55 | @ApiModelProperty(value = "Danh sách ID vai trò") 56 | private String roleIds; 57 | 58 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/permission/entity/dos/Menu.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.permission.entity.dos; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import com.myshop.orm.BaseEntity; 5 | import io.swagger.annotations.ApiModel; 6 | import io.swagger.annotations.ApiModelProperty; 7 | import lombok.Data; 8 | 9 | import java.io.Serializable; 10 | 11 | /** 12 | * Quyền menu 13 | * 14 | * @author vantrang 15 | */ 16 | @Data 17 | @TableName("myshop_menu") 18 | @ApiModel(value = "Quyền menu") 19 | public class Menu extends BaseEntity implements Serializable { 20 | 21 | private static final long serialVersionUID = 7050744476203495207L; 22 | 23 | @ApiModelProperty(value = "Tiêu đề menu") 24 | private String title; 25 | 26 | @ApiModelProperty(value = "Tên route") 27 | private String name; 28 | 29 | @ApiModelProperty(value = "Đường dẫn") 30 | private String path; 31 | 32 | @ApiModelProperty(value = "Cấp độ menu") 33 | private Integer level; 34 | 35 | @ApiModelProperty(value = "Tệp route phía client") 36 | private String frontRoute; 37 | 38 | @ApiModelProperty(value = "ID cha") 39 | private String parentId = "0"; // Giá trị mặc định 40 | 41 | @ApiModelProperty(value = "Thứ tự sắp xếp") 42 | private Double sortOrder; 43 | 44 | @ApiModelProperty(value = "URL quyền, * dùng để khớp mờ, phân cách bằng dấu phẩy") 45 | private String permission; 46 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/permission/entity/vo/UserMenuVO.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.permission.entity.vo; 2 | 3 | import com.myshop.modules.permission.entity.dos.Menu; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * Đối tượng giá trị Quyền Menu của Người Dùng (UserMenuVO) 10 | * 11 | * @author vantrang 12 | */ 13 | @Data 14 | public class UserMenuVO extends Menu implements Serializable { 15 | 16 | private static final long serialVersionUID = -7478870595109016162L; 17 | 18 | /** 19 | * Có phải Super Admin hay không 20 | */ 21 | private Boolean isSuper; 22 | 23 | /** 24 | * Lấy giá trị "Có phải Super Admin hay không". 25 | * Nếu giá trị isSuper là null, trả về false. 26 | * 27 | * @return true nếu là Super Admin, false nếu không phải hoặc null. 28 | */ 29 | public Boolean getSuper() { 30 | // Kiểm tra xem biến isSuper có null hay không 31 | if (this.isSuper == null) { 32 | // Nếu isSuper là null, trả về false 33 | return false; 34 | } 35 | return isSuper; 36 | } 37 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/permission/mapper/AdminUserMapper.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.permission.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.myshop.modules.permission.entity.dos.AdminUser; 5 | 6 | public interface AdminUserMapper extends BaseMapper { 7 | } 8 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/permission/mapper/MenuMapper.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.permission.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.myshop.modules.permission.entity.dos.Menu; 5 | import com.myshop.modules.permission.entity.vo.UserMenuVO; 6 | import org.apache.ibatis.annotations.Select; 7 | 8 | import java.util.List; 9 | 10 | public interface MenuMapper extends BaseMapper { 11 | 12 | /** 13 | * Get menu permissions based on user 14 | * 15 | * @param id user ID 16 | * @return User menu VO list 17 | */ 18 | @Select("SELECT rm.is_super as is_super,m.*FROM myshop_menu AS m INNER JOIN myshop_role_menu AS rm ON rm.menu_id=m.id WHERE rm.role_id IN (" + "SELECT ur.role_id FROM myshop_user_role AS ur WHERE ur.user_id=#{id}) OR rm.role_id IN (" + "SELECT dr.role_id FROM myshop_department_role AS dr INNER JOIN myshop_admin_user AS au ON au.department_id=dr.department_id " + "WHERE au.id=#{id}) GROUP BY m.id,rm.is_super ORDER BY rm.is_super desc") 19 | List getUserRoleMenu(String id); 20 | } 21 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/permission/service/AdminUserService.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.permission.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.myshop.common.security.token.Token; 5 | import com.myshop.modules.permission.entity.dos.AdminUser; 6 | import org.springframework.cache.annotation.CacheConfig; 7 | 8 | @CacheConfig(cacheNames = "{userAdmin}") 9 | public interface AdminUserService extends IService { 10 | 11 | /** 12 | * Đăng nhập người dùng 13 | * 14 | * @param username Tên đăng nhập 15 | * @param password Mật khẩu 16 | * @return Token 17 | */ 18 | Token login(String username, String password); 19 | 20 | /** 21 | * Tìm kiếm quản trị viên theo tên đăng nhập 22 | * 23 | * @param username Tên đăng nhập 24 | * @return Đối tượng quản trị viên hoặc null nếu không tìm thấy 25 | */ 26 | AdminUser findByUsername(String username); 27 | } 28 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/permission/service/MenuService.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.permission.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.myshop.modules.permission.entity.dos.Menu; 5 | import com.myshop.modules.permission.entity.vo.UserMenuVO; 6 | import org.springframework.cache.annotation.CacheConfig; 7 | 8 | import java.util.List; 9 | 10 | @CacheConfig(cacheNames = "{Menu}") 11 | public interface MenuService extends IService { 12 | /** 13 | * Lấy danh sách quyền menu cụ thể mà người dùng sở hữu dựa trên tập hợp vai trò. 14 | * 15 | * @param userId ID người dùng 16 | * @return Danh sách các đối tượng UserMenuVO chứa thông tin quyền menu. 17 | */ 18 | List findAllMenu(String userId); 19 | } 20 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/permission/serviceimpl/AdminUserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.permission.serviceimpl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import com.myshop.common.enums.ResultCode; 6 | import com.myshop.common.exception.ServiceException; 7 | import com.myshop.common.security.token.Token; 8 | import com.myshop.modules.permission.entity.dos.AdminUser; 9 | import com.myshop.modules.permission.mapper.AdminUserMapper; 10 | import com.myshop.modules.permission.service.AdminUserService; 11 | import com.myshop.modules.system.token.ManagerTokenProvider; 12 | import lombok.extern.slf4j.Slf4j; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 15 | import org.springframework.stereotype.Service; 16 | 17 | @Slf4j 18 | @Service 19 | public class AdminUserServiceImpl extends ServiceImpl implements AdminUserService { 20 | 21 | @Autowired 22 | private ManagerTokenProvider managerTokenProvider; 23 | 24 | @Override 25 | public Token login(String username, String password) { 26 | // Tìm kiếm adminUser dựa trên username 27 | AdminUser adminUser = this.findByUsername(username); 28 | // Kiểm tra xem adminUser có null hoặc trạng thái không hợp lệ (không hoạt động) 29 | if (adminUser == null || !adminUser.getStatus()) { 30 | // Nếu adminUser không tồn tại hoặc không hoạt động, ném ngoại lệ ServiceException với mã lỗi USER_PASSWORD_ERROR 31 | throw new ServiceException(ResultCode.USER_PASSWORD_ERROR); 32 | } 33 | // Kiểm tra xem mật khẩu nhập vào có khớp với mật khẩu đã mã hóa của adminUser 34 | if (!new BCryptPasswordEncoder().matches(password, adminUser.getPassword())) { 35 | throw new ServiceException(ResultCode.USER_PASSWORD_ERROR); 36 | } 37 | try { 38 | // Tạo token cho adminUser và trả về 39 | return managerTokenProvider.createToken(adminUser, false); 40 | } catch (Exception e) { 41 | log.error("Administrator login error", e); 42 | } 43 | return null; 44 | 45 | } 46 | 47 | @Override 48 | public AdminUser findByUsername(String username) { 49 | return getOne(new LambdaQueryWrapper().eq(AdminUser::getUsername, username), false); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/permission/serviceimpl/MenuServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.permission.serviceimpl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.myshop.modules.permission.entity.dos.Menu; 5 | import com.myshop.modules.permission.entity.vo.UserMenuVO; 6 | import com.myshop.modules.permission.mapper.MenuMapper; 7 | import com.myshop.modules.permission.service.MenuService; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.stereotype.Service; 10 | 11 | import java.util.List; 12 | 13 | @Slf4j 14 | @Service 15 | public class MenuServiceImpl extends ServiceImpl implements MenuService { 16 | 17 | @Override 18 | public List findAllMenu(String userId) { 19 | return this.baseMapper.getUserRoleMenu(userId); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/entity/dos/ProductBrand.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.entity.dos; 2 | 3 | 4 | import com.baomidou.mybatisplus.annotation.TableName; 5 | import com.myshop.orm.BaseEntity; 6 | import io.swagger.annotations.ApiModel; 7 | import io.swagger.annotations.ApiModelProperty; 8 | import jakarta.validation.constraints.NotEmpty; 9 | import lombok.Data; 10 | import org.hibernate.validator.constraints.Length; 11 | 12 | 13 | /** 14 | * Thương hiệu sản phẩm 15 | */ 16 | @Data 17 | @TableName("myshop_product_brand") 18 | @ApiModel(value = "Thương hiệu sản phẩm") 19 | public class ProductBrand extends BaseEntity { 20 | 21 | private static final long serialVersionUID = -8236865848438521426L; 22 | 23 | @NotEmpty(message = "Tên thương hiệu không được bỏ trống") 24 | @Length(max = 20, message = "Tên thương hiệu phải nhỏ hơn 20 ký tự") 25 | @ApiModelProperty(value = "Tên thương hiệu", required = true) 26 | private String name; 27 | 28 | @NotEmpty(message = "Biểu tượng thương hiệu không được bỏ trống") 29 | @Length(max = 255, message = "URL biểu tượng thương hiệu vượt quá 255 ký tự") 30 | @ApiModelProperty(value = "Biểu tượng thương hiệu", required = true) 31 | private String logo; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/entity/dos/ProductCategory.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.entity.dos; 2 | 3 | 4 | import com.baomidou.mybatisplus.annotation.TableName; 5 | import com.myshop.orm.BaseEntity; 6 | import io.swagger.annotations.ApiModel; 7 | import io.swagger.annotations.ApiModelProperty; 8 | import jakarta.validation.constraints.*; 9 | import lombok.AllArgsConstructor; 10 | import lombok.Data; 11 | import lombok.NoArgsConstructor; 12 | 13 | import java.math.BigDecimal; 14 | import java.util.Date; 15 | 16 | @Data 17 | @TableName("myshop_category") 18 | @ApiModel(value = "Danh mục sản phẩm") 19 | @AllArgsConstructor 20 | @NoArgsConstructor 21 | public class ProductCategory extends BaseEntity { 22 | 23 | private static final long serialVersionUID = 1L; 24 | 25 | @NotEmpty(message = "Tên danh mục không được để trống") 26 | @Size(max = 20) 27 | @ApiModelProperty(value = "Tên danh mục") 28 | private String name; 29 | 30 | @NotEmpty(message = "Vui lòng chọn danh mục cha") 31 | @ApiModelProperty(value = "ID của danh mục cha, nút gốc có ID là 0") 32 | private String parentId; 33 | 34 | @NotNull(message = "Cấp độ không được để trống") 35 | @Min(value = 0, message = "Cấp độ phải lớn hơn 0") 36 | @Max(value = 3, message = "Cấp độ tối đa là 3") 37 | @ApiModelProperty(value = "Cấp độ của danh mục, bắt đầu từ 0") 38 | private Integer level; 39 | 40 | @NotNull(message = "Giá trị sắp xếp không được để trống") 41 | @Max(value = 999, message = "Giá trị sắp xếp tối đa là 999") 42 | @ApiModelProperty(value = "Giá trị sắp xếp") 43 | private BigDecimal sortOrder; 44 | 45 | @ApiModelProperty(value = "Tỷ lệ hoa hồng") 46 | private Double commissionRate; 47 | 48 | @ApiModelProperty(value = "Biểu tượng của danh mục") 49 | private String image; 50 | 51 | @ApiModelProperty(value = "Hỗ trợ kênh") 52 | private Boolean isChannelSupported; 53 | 54 | public ProductCategory(String id, String createBy, Date createTime, String updateBy, Date updateTime, Boolean deleteFlag, String name, String parentId, Integer level, BigDecimal sortOrder, Double commissionRate, String image, Boolean supportChannel) { 55 | super(id, createBy, createTime, updateBy, updateTime, deleteFlag); 56 | this.name = name; 57 | this.parentId = parentId; 58 | this.level = level; 59 | this.sortOrder = sortOrder; 60 | this.commissionRate = commissionRate; 61 | this.image = image; 62 | this.isChannelSupported = supportChannel; 63 | } 64 | 65 | public ProductCategory(String id, String name, String parentId, Integer level, BigDecimal sortOrder, Double commissionRate, String image, Boolean supportChannel) { 66 | this.name = name; 67 | this.parentId = parentId; 68 | this.level = level; 69 | this.sortOrder = sortOrder; 70 | this.commissionRate = commissionRate; 71 | this.image = image; 72 | this.isChannelSupported = supportChannel; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/entity/dos/ProductCategoryBrand.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.entity.dos; 2 | 3 | import com.baomidou.mybatisplus.annotation.FieldFill; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import com.fasterxml.jackson.annotation.JsonFormat; 7 | import com.myshop.orm.IdBasedEntity; 8 | import io.swagger.annotations.ApiModel; 9 | import io.swagger.annotations.ApiModelProperty; 10 | import lombok.Data; 11 | import lombok.NoArgsConstructor; 12 | import org.springframework.data.annotation.CreatedBy; 13 | import org.springframework.data.annotation.CreatedDate; 14 | import org.springframework.format.annotation.DateTimeFormat; 15 | 16 | import java.util.Date; 17 | 18 | 19 | /** 20 | * Liên kết danh mục - thương hiệu 21 | */ 22 | @Data 23 | @TableName("myshop_product_category_brand") 24 | @ApiModel(value = "Liên kết danh mục - thương hiệu sản phẩm") 25 | @NoArgsConstructor 26 | public class ProductCategoryBrand extends IdBasedEntity { 27 | 28 | private static final long serialVersionUID = 3315719881926878L; 29 | 30 | 31 | @CreatedBy 32 | @TableField(fill = FieldFill.INSERT) 33 | @ApiModelProperty(value = "Người tạo", hidden = true) 34 | private String createdBy; 35 | 36 | @CreatedDate 37 | @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") 38 | @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") 39 | @TableField(fill = FieldFill.INSERT) 40 | @ApiModelProperty(value = "Thời gian tạo", hidden = true) 41 | private Date createdTime; 42 | 43 | /** 44 | * ID danh mục 45 | */ 46 | @TableField(value = "category_id") 47 | @ApiModelProperty(value = "ID danh mục") 48 | private String categoryId; 49 | /** 50 | * ID thương hiệu 51 | */ 52 | @TableField(value = "brand_id") 53 | @ApiModelProperty(value = "ID thương hiệu") 54 | private String brandId; 55 | 56 | public ProductCategoryBrand(String categoryId, String brandId) { 57 | this.categoryId = categoryId; 58 | this.brandId = brandId; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/entity/dos/ProductCategoryParameterGroup.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.entity.dos; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import com.myshop.orm.BaseEntity; 5 | import io.swagger.annotations.ApiModel; 6 | import io.swagger.annotations.ApiModelProperty; 7 | import jakarta.validation.constraints.NotEmpty; 8 | import jakarta.validation.constraints.NotNull; 9 | import lombok.Data; 10 | import lombok.EqualsAndHashCode; 11 | import org.hibernate.validator.constraints.Length; 12 | 13 | 14 | /** 15 | * Liên kết nhóm tham số phân loại 16 | */ 17 | @EqualsAndHashCode(callSuper = true) 18 | @Data 19 | @TableName("myshop_product_category_parameter_group") 20 | @ApiModel(value = "Liên kết nhóm tham số phân loại") 21 | public class ProductCategoryParameterGroup extends BaseEntity { 22 | 23 | private static final long serialVersionUID = -3254446505349029420L; 24 | 25 | 26 | @ApiModelProperty(value = "Tên nhóm tham số", required = true) 27 | @NotEmpty(message = "Tên nhóm tham số không được để trống") 28 | @Length(max = 20, message = "Tên nhóm tham số không được vượt quá 20 chữ") 29 | private String groupName; 30 | 31 | @ApiModelProperty(value = "ID phân loại liên kết", required = true) 32 | @NotNull(message = "Phân loại liên kết không được để trống") 33 | private String categoryId; 34 | 35 | @ApiModelProperty(value = "Sắp xếp", hidden = true) 36 | private Integer sort; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/entity/dos/ProductCategorySpecification.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.entity.dos; 2 | 3 | 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import com.myshop.orm.BaseEntity; 7 | import io.swagger.annotations.ApiModel; 8 | import io.swagger.annotations.ApiModelProperty; 9 | import lombok.AllArgsConstructor; 10 | import lombok.Data; 11 | import lombok.NoArgsConstructor; 12 | 13 | /** 14 | * Liên kết nhóm tham số phân loại 15 | */ 16 | @Data 17 | @TableName("myshop_product_category_specification") 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | @ApiModel(value = "Thông số kỹ thuật phân loại sản phẩm") 21 | public class ProductCategorySpecification extends BaseEntity { 22 | 23 | 24 | private static final long serialVersionUID = -4041367493342243147L; 25 | /** 26 | * ID phân loại 27 | */ 28 | @TableField(value = "product_category_id") 29 | @ApiModelProperty(value = "ID phân loại") 30 | private String categoryId; 31 | /** 32 | * ID thông số kỹ thuật 33 | */ 34 | @TableField(value = "product_specification_id") 35 | @ApiModelProperty(value = "ID thông số kỹ thuật") 36 | private String specificationId; 37 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/entity/dos/ProductGallery.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.entity.dos; 2 | 3 | 4 | import com.baomidou.mybatisplus.annotation.FieldFill; 5 | import com.baomidou.mybatisplus.annotation.TableField; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import com.myshop.orm.IdBasedEntity; 8 | import io.swagger.annotations.ApiModel; 9 | import io.swagger.annotations.ApiModelProperty; 10 | import lombok.Data; 11 | import org.springframework.data.annotation.CreatedBy; 12 | 13 | /** 14 | * Album ảnh sản phẩm 15 | */ 16 | @Data 17 | @TableName("myshop_product_gallery") 18 | @ApiModel(value = "Album ảnh sản phẩm") 19 | public class ProductGallery extends IdBasedEntity { 20 | 21 | 22 | @CreatedBy 23 | @TableField(fill = FieldFill.INSERT) 24 | @ApiModelProperty(value = "Người tạo", hidden = true) 25 | private String createBy; 26 | 27 | /** 28 | * ID sản phẩm 29 | */ 30 | @ApiModelProperty(value = "ID sản phẩm") 31 | private String productId; 32 | 33 | /** 34 | * Đường dẫn ảnh thu nhỏ 35 | */ 36 | @ApiModelProperty(value = "Đường dẫn ảnh thu nhỏ") 37 | private String thumbnail; 38 | 39 | /** 40 | * Đường dẫn ảnh nhỏ 41 | */ 42 | @ApiModelProperty(value = "Đường dẫn ảnh nhỏ") 43 | private String small; 44 | 45 | /** 46 | * Đường dẫn ảnh gốc 47 | */ 48 | @ApiModelProperty(value = "Đường dẫn ảnh gốc", required = true) 49 | private String original; 50 | 51 | /** 52 | * Có phải là ảnh mặc định hay không (1: có, 0: không) 53 | */ 54 | @ApiModelProperty(value = "Có phải là ảnh mặc định hay không (1: có, 0: không)") 55 | private Integer isDefault; 56 | 57 | /** 58 | * Thứ tự sắp xếp 59 | */ 60 | @ApiModelProperty(value = "Thứ tự sắp xếp", required = true) 61 | private Integer sort; 62 | 63 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/entity/dos/ProductParameters.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.entity.dos; 2 | 3 | 4 | import com.baomidou.mybatisplus.annotation.TableName; 5 | import com.myshop.orm.IdBasedEntity; 6 | import io.swagger.annotations.ApiModel; 7 | import io.swagger.annotations.ApiModelProperty; 8 | import jakarta.validation.constraints.Max; 9 | import jakarta.validation.constraints.Min; 10 | import jakarta.validation.constraints.NotEmpty; 11 | import jakarta.validation.constraints.NotNull; 12 | import lombok.Data; 13 | import lombok.EqualsAndHashCode; 14 | import org.hibernate.validator.constraints.Length; 15 | 16 | 17 | /** 18 | * Tham số sản phẩm 19 | */ 20 | @EqualsAndHashCode(callSuper = true) 21 | @Data 22 | @TableName("myshop_product_parameters") 23 | @ApiModel(value = "Tham số sản phẩm") 24 | public class ProductParameters extends IdBasedEntity { 25 | 26 | 27 | private static final long serialVersionUID = -566510714456317006L; 28 | 29 | @ApiModelProperty(value = "Tên tham số", required = true) 30 | @NotEmpty(message = "Tên tham số bắt buộc") 31 | @Length(max = 5, message = "Tên tham số không được vượt quá 5 chữ") 32 | private String paramName; 33 | 34 | 35 | @ApiModelProperty(value = "Giá trị lựa chọn") 36 | @NotEmpty(message = "Giá trị tùy chọn tham số bắt buộc") 37 | @Length(max = 255, message = "Tùy chọn tham số quá dài, vui lòng viết gọn") 38 | private String options; 39 | 40 | @ApiModelProperty(value = "Có thể lập chỉ mục hay không, 0 không hiển thị 1 hiển thị", required = true) 41 | @NotNull(message = "Có thể lập chỉ mục bắt buộc") 42 | @Min(value = 0, message = "Giá trị truyền cho có thể lập chỉ mục không chính xác") 43 | @Max(value = 1, message = "Giá trị truyền cho có thể lập chỉ mục không chính xác") 44 | private Integer isIndex; 45 | 46 | @ApiModelProperty(value = "Có phải bắt buộc hay không 1 có 0 không", required = true) 47 | @NotNull(message = "Có phải bắt buộc hay không bắt buộc") 48 | @Min(value = 0, message = "Giá trị truyền cho có phải bắt buộc hay không không chính xác") 49 | @Max(value = 1, message = "Giá trị truyền cho có phải bắt buộc hay không không chính xác") 50 | private Integer required; 51 | 52 | @ApiModelProperty(value = "ID nhóm tham số", required = true) 53 | @NotNull(message = "Nhóm tham số thuộc về không được để trống") 54 | private String groupId; 55 | 56 | @ApiModelProperty(value = "ID phân loại", hidden = true) 57 | private String categoryId; 58 | 59 | @ApiModelProperty(value = "Sắp xếp", hidden = true) 60 | @NotNull(message = "Vui lòng nhập giá trị sắp xếp") 61 | @Max(value = 9999, message = "Giá trị sắp xếp không được lớn hơn 9999") 62 | private Integer sort; 63 | 64 | } 65 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/entity/dos/ProductSpecification.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.entity.dos; 2 | 3 | 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import com.myshop.orm.IdBasedEntity; 7 | import io.swagger.annotations.ApiModel; 8 | import io.swagger.annotations.ApiModelProperty; 9 | import jakarta.validation.constraints.NotEmpty; 10 | import jakarta.validation.constraints.Size; 11 | import lombok.Data; 12 | import org.hibernate.validator.constraints.Length; 13 | 14 | 15 | /** 16 | * Thông số kỹ thuật sản phẩm 17 | */ 18 | @Data 19 | @TableName("myshop_product_specification") 20 | @ApiModel(value = "Thông số kỹ thuật") 21 | public class ProductSpecification extends IdBasedEntity { 22 | 23 | private static final long serialVersionUID = 147793597901239486L; 24 | 25 | /** 26 | * Tên thông số kỹ thuật 27 | */ 28 | @NotEmpty(message = "Tên thông số kỹ thuật không được để trống") 29 | @Size(max = 20, message = "Tên thông số kỹ thuật không được vượt quá 20 ký tự") 30 | @ApiModelProperty(value = "Tên thông số kỹ thuật", required = true) 31 | private String specName; 32 | 33 | /** 34 | * Thuộc về người bán 0 thuộc về nền tảng 35 | *

36 | * Thông số kỹ thuật tùy chỉnh của cửa hàng đã bị loại bỏ vào ngày 2021-06-23 37 | * Sẽ giới thiệu phương thức cấu hình mới trong tương lai 38 | */ 39 | @ApiModelProperty(hidden = true) 40 | private String storeId; 41 | 42 | /** 43 | * Tên giá trị thông số kỹ thuật 44 | */ 45 | @TableField(value = "product_spec_value") 46 | @ApiModelProperty(value = "Tên giá trị thông số kỹ thuật, phân cách bởi 《,》") 47 | @Length(max = 255, message = "Độ dài vượt quá giới hạn") 48 | private String specValue; 49 | 50 | 51 | } 52 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/entity/dos/ProductUnit.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.entity.dos; 2 | 3 | 4 | import com.baomidou.mybatisplus.annotation.TableName; 5 | import com.myshop.orm.BaseEntity; 6 | import io.swagger.annotations.ApiModel; 7 | import io.swagger.annotations.ApiModelProperty; 8 | import jakarta.validation.constraints.NotEmpty; 9 | import jakarta.validation.constraints.Size; 10 | import lombok.Data; 11 | 12 | 13 | /** 14 | * Đơn vị đo lường sản phẩm 15 | */ 16 | @Data 17 | @TableName("myshop_product_unit") 18 | @ApiModel(value = "Đơn vị đo lường sản phẩm") 19 | public class ProductUnit extends BaseEntity { 20 | 21 | @NotEmpty(message = "Tên đơn vị đo lường không được để trống") 22 | @Size(max = 5, message = "Độ dài tối đa của đơn vị đo lường là 5 ký tự") 23 | @ApiModelProperty(value = "Tên đơn vị đo lường") 24 | private String name; 25 | } 26 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/entity/dos/Wholesale.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.entity.dos; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import com.myshop.orm.IdBasedEntity; 5 | import io.swagger.annotations.ApiModel; 6 | import io.swagger.annotations.ApiModelProperty; 7 | import lombok.Data; 8 | import lombok.EqualsAndHashCode; 9 | 10 | 11 | @Data 12 | @EqualsAndHashCode(callSuper = true) 13 | @TableName("myshop_wholesale") 14 | @ApiModel(value = "Sản phẩm bán sỉ") 15 | public class Wholesale extends IdBasedEntity { 16 | 17 | private static final long serialVersionUID = -6387806138583086068L; 18 | 19 | @ApiModelProperty(value = "ID sản phẩm") 20 | private String goodsId; 21 | @ApiModelProperty(value = "ID SKU") 22 | private String skuId; 23 | @ApiModelProperty(value = "ID mẫu") 24 | private String templateId; 25 | @ApiModelProperty(value = "Số lượng") 26 | private Integer num; 27 | @ApiModelProperty(value = "Giá tiền") 28 | private Double price; 29 | } 30 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/entity/dto/ProductBrandPageDTO.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.entity.dto; 2 | 3 | 4 | import com.fasterxml.jackson.databind.PropertyNamingStrategy; 5 | import com.fasterxml.jackson.databind.annotation.JsonNaming; 6 | import com.myshop.common.vo.PageVO.PageVO; 7 | import io.swagger.annotations.ApiModel; 8 | import io.swagger.annotations.ApiModelProperty; 9 | import lombok.Data; 10 | 11 | /** 12 | * DTO cho thương hiệu sản phẩm 13 | */ 14 | @Data 15 | @JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) 16 | @ApiModel(description = "DTO cho thương hiệu sản phẩm") 17 | public class ProductBrandPageDTO extends PageVO { 18 | 19 | private static final long serialVersionUID = 8906820496037326039L; 20 | 21 | @ApiModelProperty(value = "Tên thương hiệu") 22 | private String name; 23 | } 24 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/entity/dto/ProductCategorySearchParams.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.entity.dto; 2 | 3 | 4 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 5 | import io.swagger.annotations.ApiModelProperty; 6 | import lombok.Data; 7 | 8 | import java.math.BigDecimal; 9 | 10 | /** 11 | * Tham số tìm kiếm danh mục 12 | **/ 13 | @Data 14 | public class ProductCategorySearchParams { 15 | 16 | @ApiModelProperty(value = "Tên danh mục") 17 | private String name; 18 | 19 | @ApiModelProperty(value = "ID của danh mục cha") 20 | private String parentId; 21 | 22 | @ApiModelProperty(value = "Cấp độ") 23 | private Integer level; 24 | 25 | @ApiModelProperty(value = "Giá trị sắp xếp") 26 | private BigDecimal sortOrder; 27 | 28 | @ApiModelProperty(value = "Tỷ lệ hoa hồng") 29 | private BigDecimal commissionRate; 30 | 31 | @ApiModelProperty(value = "Tên của nút cha") 32 | private String parentTitle; 33 | 34 | @ApiModelProperty(value = "Có bị vô hiệu hóa hay không") 35 | private Boolean deleteFlag; 36 | 37 | public QueryWrapper searchWrapper() { 38 | QueryWrapper searchWrapper = new QueryWrapper<>(); 39 | searchWrapper.like(name != null, "name", name); 40 | searchWrapper.like(parentTitle != null, "parent_title", parentTitle); 41 | searchWrapper.eq(parentId != null, "parent_id", parentId); 42 | searchWrapper.eq(level != null, "level", level); 43 | searchWrapper.eq(sortOrder != null, "sort_order", sortOrder); 44 | searchWrapper.eq(commissionRate != null, "commission_rate", commissionRate); 45 | searchWrapper.eq(deleteFlag != null, "delete_flag", deleteFlag); 46 | return searchWrapper; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/entity/dto/ProductImportDTO.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.entity.dto; 2 | 3 | import com.myshop.modules.product.entity.dos.ProductCategory; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * DTO nhập sản phẩm 13 | */ 14 | @Data 15 | @NoArgsConstructor 16 | @AllArgsConstructor 17 | public class ProductImportDTO { 18 | 19 | @ApiModelProperty(value = "Tên sản phẩm") 20 | private String productName; 21 | 22 | @ApiModelProperty(value = "Điểm bán hàng") 23 | private String productHighlight; 24 | 25 | @ApiModelProperty(value = "Phân loại sản phẩm") 26 | private ProductCategory productCategory; 27 | 28 | @ApiModelProperty(value = "Mẫu vận chuyển") 29 | private String shippingTemplate; 30 | 31 | @ApiModelProperty(value = "Đơn vị đo lường") 32 | private String goodsUnit; 33 | 34 | @ApiModelProperty(value = "Trạng thái xuất bản") 35 | private Boolean isPublished; 36 | 37 | @ApiModelProperty(value = "Hình ảnh sản phẩm") 38 | private List images; 39 | private List galleryImages; 40 | 41 | @ApiModelProperty(value = "Giá vốn") 42 | private Double costPrice; 43 | 44 | @ApiModelProperty(value = "Giá bán") 45 | private Double sellingPrice; 46 | 47 | @ApiModelProperty(value = "Số lượng tồn kho") 48 | private Integer quantity; 49 | 50 | @ApiModelProperty(value = "Trọng lượng") 51 | private Double weight; 52 | 53 | @ApiModelProperty(value = "Mã SKU") 54 | private String sku; 55 | 56 | @ApiModelProperty(value = "Mô tả") 57 | private String description; 58 | 59 | @ApiModelProperty(value = "Tên thuộc tính") 60 | private String skuName; 61 | 62 | @ApiModelProperty(value = "Giá trị thuộc tính") 63 | private String skuValue; 64 | 65 | 66 | } 67 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/entity/dto/ProductParamsDTO.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.entity.dto; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableField; 4 | import io.swagger.annotations.ApiModel; 5 | import io.swagger.annotations.ApiModelProperty; 6 | import lombok.Data; 7 | 8 | import java.io.Serializable; 9 | import java.util.List; 10 | 11 | /** 12 | * Thông số liên quan đến sản phẩm 13 | */ 14 | @Data 15 | @ApiModel(value = "Nhóm thông số sản phẩm") 16 | public class ProductParamsDTO implements Serializable { 17 | 18 | private static final long serialVersionUID = 4892783539320159200L; 19 | 20 | @TableField(value = "group_id") 21 | @ApiModelProperty(value = "ID nhóm") 22 | private String groupId; 23 | 24 | @TableField(value = "group_name") 25 | @ApiModelProperty(value = "Tên nhóm") 26 | private String groupName; 27 | 28 | @ApiModelProperty(value = "Danh sách thông số sản phẩm trong nhóm") 29 | private List productParamsItemDTOList; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/entity/dto/ProductParamsItemDTO.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.entity.dto; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * Thông số sản phẩm 11 | */ 12 | @Data 13 | @ApiModel(value = "Danh sách thông số sản phẩm") 14 | public class ProductParamsItemDTO implements Serializable { 15 | 16 | private static final long serialVersionUID = -8823775607604091035L; 17 | 18 | @ApiModelProperty(value = "ID thông số") 19 | private String paramId; 20 | 21 | @ApiModelProperty(value = "Tên thông số") 22 | private String paramName; 23 | 24 | @ApiModelProperty(value = "Giá trị thông số") 25 | private String paramValue; 26 | 27 | @ApiModelProperty(value = "Cho phép lập chỉ mục, 0 không lập chỉ mục, 1 lập chỉ mục") 28 | private Integer isIndex = 0; 29 | 30 | @ApiModelProperty(value = "Bắt buộc nhập, 0 không hiển thị, 1 hiển thị") 31 | private Integer required = 0; 32 | 33 | @ApiModelProperty(value = "Thứ tự sắp xếp") 34 | private Integer sort; 35 | } 36 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/entity/dto/WholesaleDTO.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.entity.dto; 2 | 3 | import com.myshop.modules.product.entity.dos.Wholesale; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | import lombok.NoArgsConstructor; 7 | import org.springframework.beans.BeanUtils; 8 | 9 | /** 10 | * Quy tắc bán sỉ DTO 11 | */ 12 | @Data 13 | @EqualsAndHashCode(callSuper = true) 14 | @NoArgsConstructor 15 | public class WholesaleDTO extends Wholesale { 16 | 17 | private static final long serialVersionUID = 853287561151783335L; 18 | 19 | public WholesaleDTO(Wholesale wholesale) { 20 | BeanUtils.copyProperties(wholesale, this); 21 | } 22 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/entity/enums/ProductAuthEnum.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.entity.enums; 2 | 3 | /** 4 | * Phê duyệt sản phẩm 5 | */ 6 | public enum ProductAuthEnum { 7 | /** 8 | * Cần phê duyệt và đang chờ phê duyệt 9 | */ 10 | PENDING("Đang chờ phê duyệt"), 11 | /** 12 | * Phê duyệt thành công 13 | */ 14 | PASS("Phê duyệt thành công"), 15 | /** 16 | * Từ chối phê duyệt 17 | */ 18 | REFUSE("Từ chối phê duyệt"); 19 | 20 | private final String description; 21 | 22 | ProductAuthEnum(String description) { 23 | this.description = description; 24 | } 25 | 26 | public String description() { 27 | return description; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/entity/enums/ProductSalesModeEnum.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.entity.enums; 2 | 3 | /** 4 | * Chế độ bán hàng 5 | */ 6 | public enum ProductSalesModeEnum { 7 | 8 | RETAIL("Bán lẻ"), 9 | WHOLESALE("Bán sỉ"); 10 | 11 | private final String description; 12 | 13 | ProductSalesModeEnum(String description) { 14 | this.description = description; 15 | 16 | } 17 | 18 | public String description() { 19 | return description; 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/entity/enums/ProductStatusEnum.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.entity.enums; 2 | 3 | /** 4 | * Kiểu sản phẩm enum 5 | */ 6 | public enum ProductStatusEnum { 7 | /** 8 | * Đang kinh doanh 9 | */ 10 | UPPER("Đang kinh doanh"), 11 | /** 12 | * Ngừng kinh doanh 13 | */ 14 | DOWN("Ngừng kinh doanh"); 15 | 16 | private final String description; 17 | 18 | ProductStatusEnum(String description) { 19 | this.description = description; 20 | } 21 | 22 | public String description() { 23 | return description; 24 | } 25 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/entity/enums/ProductTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.entity.enums; 2 | 3 | /** 4 | * Loại sản phẩm 5 | * 6 | */ 7 | public enum ProductTypeEnum { 8 | 9 | /** 10 | * "Sản phẩm vật lý" 11 | */ 12 | PHYSICAL_PRODUCT("Sản phẩm vật lý"), 13 | /** 14 | * "Sản phẩm kỹ thuật số" 15 | */ 16 | VIRTUAL_PRODUCT("Sản phẩm kỹ thuật số"), 17 | /** 18 | * "Phiếu quà tặng điện tử" 19 | */ 20 | E_COUPON("Phiếu quà tặng điện tử"); 21 | 22 | 23 | private final String description; 24 | 25 | ProductTypeEnum(String description) { 26 | this.description = description; 27 | } 28 | 29 | public String description() { 30 | return description; 31 | } 32 | 33 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/entity/vos/ProductBrandVO.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.entity.vos; 2 | 3 | import com.myshop.modules.product.entity.dos.ProductBrand; 4 | 5 | public class ProductBrandVO extends ProductBrand { 6 | 7 | private static final long serialVersionUID = 3829199981161122317L; 8 | } 9 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/entity/vos/ProductCategoryVO.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.entity.vos; 2 | 3 | import cn.hutool.core.bean.BeanUtil; 4 | import com.myshop.modules.product.entity.dos.ProductCategory; 5 | import com.myshop.modules.product.entity.dos.ProductBrand; 6 | import io.swagger.annotations.ApiModelProperty; 7 | import lombok.AllArgsConstructor; 8 | import lombok.Data; 9 | import lombok.NoArgsConstructor; 10 | 11 | import java.math.BigDecimal; 12 | import java.util.Comparator; 13 | import java.util.Date; 14 | import java.util.List; 15 | 16 | /** 17 | * VO (Value Object) của phân loại hàng hóa 18 | **/ 19 | @Data 20 | @NoArgsConstructor 21 | @AllArgsConstructor 22 | public class ProductCategoryVO extends ProductCategory { 23 | 24 | // Tự tìm hiểu thêm serialize và deserialize trong java nha! 25 | private static final long serialVersionUID = 3775766246076838410L; 26 | 27 | @ApiModelProperty(value = "Tên của nút cha") 28 | private String parentTitle; 29 | 30 | @ApiModelProperty("Danh sách phân loại con") 31 | private List childCategories; 32 | 33 | @ApiModelProperty("Danh sách thương hiệu liên kết với phân loại") 34 | private List brandList; 35 | 36 | public ProductCategoryVO(ProductCategory cat) { 37 | BeanUtil.copyProperties(cat, this); 38 | } 39 | 40 | public ProductCategoryVO(String id, String createdBy, Date createdTime, String updatedBy, Date updatedTime, Boolean deleted, String name, String parentId, Integer level, BigDecimal sortOrder, Double commissionRate, String image, Boolean supportChannel) { 41 | super(id, createdBy, createdTime, updatedBy, updatedTime, deleted, name, parentId, level, sortOrder, commissionRate, image, supportChannel); 42 | } 43 | 44 | public List getChildCategories() { 45 | if (childCategories != null) { 46 | childCategories.sort(new Comparator() { 47 | @Override 48 | public int compare(ProductCategoryVO o1, ProductCategoryVO o2) { 49 | return o1.getSortOrder().compareTo(o2.getSortOrder()); 50 | } 51 | }); 52 | return childCategories; 53 | } 54 | return null; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/entity/vos/ProductParameterGroupVO.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.entity.vos; 2 | 3 | 4 | import com.myshop.modules.product.entity.dos.ProductParameters; 5 | import io.swagger.annotations.ApiModel; 6 | import io.swagger.annotations.ApiModelProperty; 7 | import lombok.Data; 8 | 9 | import java.io.Serializable; 10 | import java.util.List; 11 | 12 | /** 13 | * VO nhóm tham số 14 | */ 15 | @ApiModel 16 | @Data 17 | public class ProductParameterGroupVO implements Serializable { 18 | 19 | private static final long serialVersionUID = 724447321881170297L; 20 | 21 | @ApiModelProperty("Bộ sưu tập tham số liên kết với nhóm tham số") 22 | private List params; 23 | 24 | @ApiModelProperty(value = "Tên nhóm tham số") 25 | private String groupName; 26 | 27 | @ApiModelProperty(value = "ID nhóm tham số") 28 | private String groupId; 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/entity/vos/ProductSkuVO.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.entity.vos; 2 | 3 | 4 | import cn.hutool.core.bean.BeanUtil; 5 | import com.myshop.modules.product.entity.dos.ProductSku; 6 | import io.swagger.annotations.ApiModelProperty; 7 | import lombok.AllArgsConstructor; 8 | import lombok.Data; 9 | import lombok.EqualsAndHashCode; 10 | import lombok.NoArgsConstructor; 11 | 12 | import java.util.List; 13 | 14 | /** 15 | * VO Thông số kỹ thuật sản phẩm 16 | */ 17 | @Data 18 | @EqualsAndHashCode(callSuper = true) 19 | @NoArgsConstructor 20 | @AllArgsConstructor 21 | public class ProductSkuVO extends ProductSku { 22 | 23 | private static final long serialVersionUID = -7651149660489332344L; 24 | 25 | @ApiModelProperty(value = "Danh sách thông số kỹ thuật") 26 | private List specList; 27 | 28 | @ApiModelProperty(value = "Hình ảnh sản phẩm") 29 | private List productGalleryList; 30 | 31 | public ProductSkuVO(ProductSku productSku) { 32 | BeanUtil.copyProperties(productSku, this); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/entity/vos/ProductSpecValueVO.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.entity.vos; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableField; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | import java.util.List; 9 | 10 | /** 11 | * Giá trị thông số kỹ thuật 12 | */ 13 | @Data 14 | public class ProductSpecValueVO implements Serializable { 15 | 16 | private static final long serialVersionUID = -4433569132929428572L; 17 | 18 | @TableField(value = "spec_attribute_name") 19 | @ApiModelProperty(value = "Tên thuộc tính thông số kỹ thuật") 20 | private String specAttributeName; 21 | 22 | @TableField(value = "spec_attribute_value") 23 | @ApiModelProperty(value = "Giá trị thuộc tính thông số kỹ thuật") 24 | private String specAttributeValue; 25 | 26 | @ApiModelProperty(value = "Thông số kỹ thuật này có hình ảnh hay không, 1 là có, 0 là không") 27 | private Integer hasSpecImage; 28 | /** 29 | * Hình ảnh thông số kỹ thuật 30 | */ 31 | @ApiModelProperty(value = "Danh sách hình ảnh thuộc tính thông số kỹ thuật") 32 | private List specAttributeImages; 33 | } 34 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/entity/vos/ProductVO.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.entity.vos; 2 | 3 | 4 | import com.myshop.modules.product.entity.dos.Product; 5 | import com.myshop.modules.product.entity.dos.Wholesale; 6 | import com.myshop.modules.product.entity.dto.ProductParamsDTO; 7 | import io.swagger.annotations.ApiModelProperty; 8 | import lombok.Data; 9 | import lombok.EqualsAndHashCode; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * VO sản phẩm 15 | */ 16 | @Data 17 | @EqualsAndHashCode(callSuper = true) 18 | public class ProductVO extends Product { 19 | 20 | private static final long serialVersionUID = 6377723919990713567L; 21 | 22 | @ApiModelProperty(value = "Tên danh mục") 23 | private List categoryName; 24 | 25 | @ApiModelProperty(value = "Thông số sản phẩm") 26 | private List productParamsDTOList; 27 | 28 | @ApiModelProperty(value = "Hình ảnh sản phẩm") 29 | private List productGalleryList; 30 | 31 | @ApiModelProperty(value = "Danh sách SKU") 32 | private List skuList; 33 | 34 | @ApiModelProperty(value = "Danh sách quy tắc mua sỉ sản phẩm") 35 | private List wholesaleRules; 36 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/mapper/CategoryMapper.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.myshop.modules.product.entity.dos.ProductCategory; 5 | 6 | public interface CategoryMapper extends BaseMapper { 7 | } 8 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/mapper/MemberMapper.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.myshop.modules.member.entity.dos.Member; 5 | 6 | public interface MemberMapper extends BaseMapper { 7 | } 8 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/mapper/ProductBrandMapper.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.myshop.modules.product.entity.dos.ProductBrand; 5 | 6 | public interface ProductBrandMapper extends BaseMapper { 7 | } 8 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/mapper/ProductCategoryBrandMapper.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.myshop.modules.product.entity.dos.ProductCategoryBrand; 5 | 6 | public interface ProductCategoryBrandMapper extends BaseMapper { 7 | } 8 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/mapper/ProductCategoryParameterGroupMapper.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.myshop.modules.product.entity.dos.ProductCategoryParameterGroup; 5 | 6 | public interface ProductCategoryParameterGroupMapper extends BaseMapper { 7 | } 8 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/mapper/ProductCategorySpecificationMapper.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.myshop.modules.product.entity.dos.ProductCategorySpecification; 5 | import com.myshop.modules.product.entity.dos.ProductSpecification; 6 | import org.apache.ibatis.annotations.Select; 7 | 8 | import java.util.List; 9 | 10 | public interface ProductCategorySpecificationMapper extends BaseMapper { 11 | /** 12 | * Truy vấn thông số kỹ thuật liên kết theo ID phân loại 13 | * 14 | * @param categoryId ID phân loại 15 | * @return Danh sách thông số kỹ thuật liên kết phân loại 16 | */ 17 | @Select("select s.* from myshop_product_specification s INNER join myshop_product_category_specification cs " + "on s.id = cs.product_specification_id and cs.product_category_id = #{categoryId} ") 18 | List getProductCategorySpecList(String categoryId); 19 | } 20 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/mapper/ProductGalleryMapper.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.myshop.modules.product.entity.dos.ProductGallery; 5 | 6 | public interface ProductGalleryMapper extends BaseMapper { 7 | } 8 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/mapper/ProductMapper.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.myshop.modules.product.entity.dos.Product; 5 | 6 | public interface ProductMapper extends BaseMapper { 7 | } 8 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/mapper/ProductParametersMapper.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.myshop.modules.product.entity.dos.ProductParameters; 5 | 6 | public interface ProductParametersMapper extends BaseMapper { 7 | } 8 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/mapper/ProductSkuMapper.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.myshop.modules.product.entity.dos.ProductSku; 5 | 6 | public interface ProductSkuMapper extends BaseMapper { 7 | } 8 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/mapper/ProductSpecificationMapper.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.myshop.modules.product.entity.dos.ProductSpecification; 5 | 6 | public interface ProductSpecificationMapper extends BaseMapper { 7 | } 8 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/mapper/ProductUnitMapper.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.myshop.modules.product.entity.dos.ProductUnit; 5 | 6 | public interface ProductUnitMapper extends BaseMapper { 7 | } 8 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/service/ProductBrandService.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.service; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.baomidou.mybatisplus.extension.service.IService; 5 | import com.myshop.modules.product.entity.dos.ProductBrand; 6 | import com.myshop.modules.product.entity.dto.ProductBrandPageDTO; 7 | import com.myshop.modules.product.entity.vos.ProductBrandVO; 8 | import jakarta.validation.Valid; 9 | 10 | import java.util.List; 11 | 12 | public interface ProductBrandService extends IService { 13 | 14 | /** 15 | * Lấy danh sách thương hiệu theo phân trang dựa trên điều kiện 16 | * 17 | * @param page Tham số điều kiện 18 | * @return Danh sách thương hiệu 19 | */ 20 | IPage getProductBrandsByPage(ProductBrandPageDTO page); 21 | 22 | /** 23 | * Thêm thương hiệu 24 | * 25 | * @param brandVO Thông tin thương hiệu 26 | * @return Kết quả thêm 27 | */ 28 | boolean addProductBrand(@Valid ProductBrandVO brandVO); 29 | 30 | /** 31 | * Cập nhật thương hiệu 32 | * 33 | * @param brandVO Thông tin thương hiệu 34 | * @return Kết quả cập nhật 35 | */ 36 | boolean updateProductBrand(@Valid ProductBrandVO brandVO); 37 | 38 | /** 39 | * Cập nhật trạng thái có thể sử dụng của thương hiệu 40 | * 41 | * @param brandId ID thương hiệu 42 | * @param disable Có không thể sử dụng hay không 43 | * @return Kết quả cập nhật 44 | */ 45 | boolean productBrandDisable(String brandId, Boolean disable); 46 | 47 | /** 48 | * Xóa thương hiệu 49 | * 50 | * @param ids Danh sách ID thương hiệu 51 | */ 52 | void deleteProductBrands(List ids); 53 | } 54 | 55 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/service/ProductCategoryBrandService.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.myshop.modules.product.entity.dos.ProductCategoryBrand; 5 | 6 | import java.util.List; 7 | 8 | public interface ProductCategoryBrandService extends IService { 9 | /** 10 | * Lấy thông tin liên kết danh mục - thương hiệu dựa trên ID thương hiệu 11 | * 12 | * @param brandIds ID thương hiệu 13 | * @return Thông tin liên kết danh mục - thương hiệu 14 | */ 15 | List getCategoryBrandsByBrandIds(List brandIds); 16 | 17 | /** 18 | * Xóa các thương hiệu liên kết theo ID loại sản phẩm 19 | * 20 | * @param categoryId ID của loại sản phẩm 21 | */ 22 | void deleteByProductCategoryId(String categoryId); 23 | } 24 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/service/ProductCategoryParameterGroupService.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.myshop.modules.product.entity.dos.ProductCategoryParameterGroup; 5 | import com.myshop.modules.product.entity.vos.ProductParameterGroupVO; 6 | 7 | import java.util.List; 8 | 9 | public interface ProductCategoryParameterGroupService extends IService { 10 | 11 | /** 12 | * Truy vấn bộ sưu tập tham số được liên kết với phân loại 13 | * 14 | * @param categoryId ID phân loại 15 | * @return Tham số phân loại 16 | */ 17 | List getProductCategoryParams(String categoryId); 18 | 19 | /** 20 | * Truy vấn thông tin nhóm tham số được liên kết với phân loại 21 | * 22 | * @param categoryId ID phân loại 23 | * @return Danh sách nhóm tham số 24 | */ 25 | List getProductCategoryGroup(String categoryId); 26 | 27 | /** 28 | * Xóa các thương hiệu liên kết theo ID loại sản phẩm 29 | * 30 | * @param categoryId ID của loại sản phẩm 31 | */ 32 | void deleteByProductCategoryId(String categoryId); 33 | } 34 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/service/ProductCategoryService.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.myshop.modules.product.entity.dos.ProductCategory; 5 | import com.myshop.modules.product.entity.dto.ProductCategorySearchParams; 6 | import com.myshop.modules.product.entity.vos.ProductCategoryVO; 7 | import jakarta.validation.Valid; 8 | 9 | import java.util.List; 10 | 11 | public interface ProductCategoryService extends IService { 12 | 13 | /** 14 | * Lấy danh sách tất cả các phân loại, bao gồm cả quan hệ cha-con 15 | * 16 | * @param parentId ID của phân loại cha 17 | * @return Danh sách tất cả các phân loại, bao gồm cả quan hệ cha-con 18 | */ 19 | List listSubCategories(String parentId); 20 | 21 | /** 22 | * Lấy cây phân loại 23 | * 24 | * @return Cây phân loại 25 | */ 26 | List getCategoryTree(); 27 | 28 | /** 29 | * Lấy tên danh mục theo danh sách ID danh mục đã cho 30 | * 31 | * @param categoryIds Danh sách ID danh mục 32 | * @return Danh sách tên danh mục 33 | */ 34 | Object getProductCategoryNameByIds(List categoryIds); 35 | 36 | 37 | /** 38 | * Quản trị viên lấy tất cả các danh mục 39 | * Nghĩa là các đối tượng được lấy, cho dù đã bị xóa hay chưa, đều được hiển thị, và không lấy từ bộ nhớ cache, đảm bảo nội dung là mới nhất 40 | * 41 | * @param parentId ID của danh mục cha 42 | * @return Danh sách danh mục sản phẩm 43 | */ 44 | List getAllCategories(String parentId); 45 | 46 | /** 47 | * Truy vấn tất cả các danh mục, bao gồm cả mối quan hệ cha-con 48 | * Lấy dữ liệu từ cơ sở dữ liệu 49 | * 50 | * @param categorySearchParams Tham số tìm kiếm 51 | * @return Tất cả các danh mục, bao gồm cả mối quan hệ cha-con 52 | */ 53 | List getAllChildren(ProductCategorySearchParams categorySearchParams); 54 | 55 | /** 56 | * Truy vấn tất cả các danh mục, bao gồm cả mối quan hệ cha-con 57 | * 58 | * @param parentId ID của danh mục cha 59 | * @return Tất cả các danh mục, bao gồm cả mối quan hệ cha-con 60 | */ 61 | List getAllChildren(String parentId); 62 | 63 | /** 64 | * Thêm loại sản phẩm 65 | * 66 | * @param productCategory Thông tin loại sản phẩm 67 | * @return Kết quả thêm 68 | */ 69 | boolean saveCategory(@Valid ProductCategory productCategory); 70 | 71 | /** 72 | * Sửa đổi loại sản phẩm 73 | * 74 | * @param productCategory Thông tin loại sản phẩm 75 | * @return Kết quả sửa đổi 76 | */ 77 | void updateCategory(@Valid ProductCategoryVO productCategory); 78 | 79 | /** 80 | * Lấy danh sách loại sản phẩm 81 | * 82 | * @param productCategory Loại sản phẩm 83 | * @return Danh sách loại sản phẩm 84 | */ 85 | List findByAllBySortOrder(ProductCategory productCategory); 86 | 87 | /** 88 | * Xóa nhiều loại sản phẩm 89 | * 90 | * @param id ID của loại sản phẩm 91 | */ 92 | void delete(String id); 93 | 94 | /** 95 | * Thay đổi trạng thái của loại sản phẩm 96 | * 97 | * @param categoryId ID của loại sản phẩm 98 | * @param enable Cho phép sử dụng hay không 99 | */ 100 | void updateProductCategoryStatus(String categoryId, Boolean enable); 101 | } 102 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/service/ProductCategorySpecificationService.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.myshop.modules.product.entity.dos.ProductCategorySpecification; 5 | import com.myshop.modules.product.entity.dos.ProductSpecification; 6 | 7 | import java.util.List; 8 | 9 | public interface ProductCategorySpecificationService extends IService { 10 | /** 11 | * Truy vấn thông tin thông số kỹ thuật theo ID phân loại 12 | * 13 | * @param categoryId ID phân loại 14 | * @return Thông tin liên kết thông số kỹ thuật phân loại 15 | */ 16 | List getProductCategorySpecList(String categoryId); 17 | 18 | /** 19 | * Xóa các thông số kỹ thuật liên kết theo ID loại sản phẩm 20 | * 21 | * @param categoryId ID của loại sản phẩm 22 | */ 23 | void deleteByProductCategoryId(String categoryId); 24 | } 25 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/service/ProductGalleryService.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.myshop.modules.product.entity.dos.ProductGallery; 5 | 6 | import java.util.List; 7 | 8 | public interface ProductGalleryService extends IService { 9 | 10 | /** 11 | * Lấy ảnh thu nhỏ từ ảnh gốc 12 | * 13 | * @param origin Đường dẫn ảnh gốc 14 | * @return Album ảnh sản phẩm 15 | */ 16 | ProductGallery getProductGallery(String origin); 17 | 18 | /** 19 | * Thêm album ảnh sản phẩm 20 | * 21 | * @param productGalleryList Danh sách album ảnh sản phẩm 22 | * @param goodsId ID sản phẩm 23 | */ 24 | void add(List productGalleryList, String goodsId); 25 | 26 | /** 27 | * Tìm kiếm album ảnh sản phẩm theo ID sản phẩm 28 | * 29 | * @param productId ID sản phẩm 30 | * @return Danh sách album ảnh sản phẩm 31 | */ 32 | List productGalleryList(String productId); 33 | } 34 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/service/ProductParametersService.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.myshop.modules.product.entity.dos.ProductParameters; 5 | import jakarta.validation.Valid; 6 | 7 | public interface ProductParametersService extends IService { 8 | /** 9 | * Cập nhật thông tin nhóm tham số 10 | * 11 | * @param productParameters Thông tin nhóm tham số 12 | * @return Cập nhật thành công hay không 13 | */ 14 | boolean updateProductParameter(@Valid ProductParameters productParameters); 15 | } 16 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/service/ProductService.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.service; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.baomidou.mybatisplus.extension.service.IService; 5 | import com.myshop.modules.product.entity.dos.Product; 6 | import com.myshop.modules.product.entity.dos.ProductCategory; 7 | import com.myshop.modules.product.entity.dos.ProductSearchParams; 8 | import com.myshop.modules.product.entity.dto.ProductOperationDTO; 9 | import com.myshop.modules.product.entity.enums.ProductStatusEnum; 10 | import com.myshop.modules.product.entity.vos.ProductVO; 11 | import jakarta.validation.constraints.NotNull; 12 | 13 | import java.util.List; 14 | 15 | public interface ProductService extends IService { 16 | 17 | /** 18 | * Thêm sản phẩm 19 | * 20 | * @param productOperationDTO Điều kiện tìm kiếm sản phẩm 21 | */ 22 | void addProduct(ProductOperationDTO productOperationDTO); 23 | 24 | /** 25 | * Truy vấn sản phẩm 26 | * 27 | * @param productSearchParams Tham số truy vấn 28 | * @return Phân trang sản phẩm 29 | */ 30 | IPage getByParams(ProductSearchParams productSearchParams); 31 | 32 | /** 33 | * Cập nhật trạng thái đưa sản phẩm lên kệ 34 | * 35 | * @param productIds Danh sách ID sản phẩm 36 | * @param productStatusEnum Trạng thái sản phẩm cần cập nhật 37 | * @param underReason Lý do đưa sản phẩm xuống kệ 38 | * @return Kết quả cập nhật 39 | */ 40 | Boolean updateProductMarketAble(List productIds, ProductStatusEnum productStatusEnum, String underReason); 41 | 42 | /** 43 | * Cập nhật trạng thái lên kệ của sản phẩm 44 | * 45 | * @param productIds Danh sách ID sản phẩm 46 | * @param productStatusEnum Trạng thái sản phẩm cần cập nhật 47 | * @param underReason Lý do xuống kệ 48 | * @return Kết quả cập nhật 49 | */ 50 | Boolean managerUpdateProductMarketAble(List productIds, ProductStatusEnum productStatusEnum, String underReason); 51 | 52 | /** 53 | * Tìm kiếm sản phẩm VO 54 | * 55 | * @param productId ID sản phẩm 56 | * @return VO sản phẩm 57 | */ 58 | ProductVO getProductVO(String productId); 59 | 60 | /** 61 | * Lấy sản phẩm dựa trên ID thương hiệu 62 | * 63 | * @param brandIds Danh sách ID thương hiệu 64 | */ 65 | List getByBrandIds(List brandIds); 66 | 67 | /** 68 | * Cập nhật thông tin tham số sản phẩm 69 | * 70 | * @param productId ID của sản phẩm 71 | * @param params Thông tin tham số sản phẩm 72 | */ 73 | void updateProductParams(String productId, String params); 74 | 75 | 76 | /** 77 | * Lấy số lượng sản phẩm thuộc một loại sản phẩm nhất định 78 | * 79 | * @param categoryId ID của loại sản phẩm 80 | * @return Số lượng sản phẩm 81 | */ 82 | long getProductCountByCategory(@NotNull String categoryId); 83 | } 84 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/service/ProductSkuService.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.myshop.cache.CachePrefix; 5 | import com.myshop.modules.product.entity.dos.Product; 6 | import com.myshop.modules.product.entity.dos.ProductSku; 7 | import com.myshop.modules.product.entity.vos.ProductSkuVO; 8 | 9 | import java.util.List; 10 | 11 | public interface ProductSkuService extends IService { 12 | 13 | /** 14 | * Lấy ID bộ nhớ cache của sản phẩm SKU 15 | * 16 | * @param id Id của SKU 17 | * @return ID bộ nhớ cache của sản phẩm SKU 18 | */ 19 | static String getSkuCacheId(String id) { 20 | return CachePrefix.PRODUCT_SKU.getPrefix() + id; 21 | } 22 | 23 | /** 24 | * Cập nhật trạng thái sản phẩm SKU 25 | * 26 | * @param product Thông tin sản phẩm (Id, DisplayStatus/IsApproved) 27 | */ 28 | void updateProductSkuStatus(Product product); 29 | 30 | 31 | /** 32 | * Lấy danh sách tất cả các goodsSku thuộc goodsId 33 | * 34 | * @param productId Id của sản phẩm 35 | * @return Danh sách goodsSku 36 | */ 37 | List getProductSkuListByProductId(String productId); 38 | 39 | /** 40 | * Lấy danh sách ProductSku theo ID sản phẩm 41 | * 42 | * @param productId ID sản phẩm 43 | * @return Danh sách ProductSku 44 | */ 45 | List getProductListByProductId(String productId); 46 | 47 | /** 48 | * Tạo danh sách ProductSkuVO từ danh sách ProductSku 49 | * 50 | * @param list Danh sách ProductSku 51 | * @return Danh sách ProductSkuVO 52 | */ 53 | List getProductSkuVOList(List list); 54 | 55 | /** 56 | * Tạo ProductSkuVO từ thông tin ProductSku 57 | * 58 | * @param productSku Thông tin ProductSku 59 | * @return ProductSkuVO 60 | */ 61 | ProductSkuVO getProductSkuVO(ProductSku productSku); 62 | } 63 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/service/ProductSpecificationService.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.myshop.modules.product.entity.dos.ProductSpecification; 5 | 6 | import java.util.List; 7 | 8 | public interface ProductSpecificationService extends IService { 9 | /** 10 | * Xóa thông số kỹ thuật 11 | * 12 | * @param ids ID thông số kỹ thuật 13 | * @return Liệu việc xóa có thành công hay không 14 | */ 15 | boolean deleteProductSpecification(List ids); 16 | } 17 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/service/ProductUnitService.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.myshop.modules.product.entity.dos.ProductUnit; 5 | 6 | public interface ProductUnitService extends IService { 7 | } 8 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/serviceimpl/MemberServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.serviceimpl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import com.myshop.common.enums.ResultCode; 6 | import com.myshop.common.exception.ServiceException; 7 | import com.myshop.common.security.token.Token; 8 | import com.myshop.modules.member.entity.dos.Member; 9 | import com.myshop.modules.member.service.MemberService; 10 | import com.myshop.modules.member.token.MemberTokenProvider; 11 | import com.myshop.modules.product.mapper.MemberMapper; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 14 | import org.springframework.stereotype.Service; 15 | 16 | @Service 17 | public class MemberServiceImpl extends ServiceImpl implements MemberService { 18 | 19 | @Autowired 20 | private MemberTokenProvider memberTokenProvider; 21 | 22 | @Override 23 | public Token login(String username, String password) { 24 | Member foundMember = this.findMember(username); 25 | // Kiểm tra xem người dùng có tồn tại hay không 26 | if (foundMember == null || !foundMember.getDisabled()) { 27 | throw new ServiceException(ResultCode.USER_NOT_FOUND); 28 | } 29 | // Kiểm tra xem mật khẩu có chính xác hay không 30 | if (!new BCryptPasswordEncoder().matches(password, foundMember.getPassword())) { 31 | throw new ServiceException(ResultCode.USER_PASSWORD_ERROR); 32 | } 33 | return memberTokenProvider.createToken(foundMember, false); 34 | } 35 | 36 | /** 37 | * Truyền số điện thoại hoặc tên đăng nhập 38 | * 39 | * @param userName Số điện thoại hoặc tên đăng nhập 40 | * @return Thông tin thành viên 41 | */ 42 | private Member findMember(String userName) { 43 | QueryWrapper query = new QueryWrapper<>(); 44 | query.eq("username", userName).or().eq("mobile", userName); 45 | return this.getOne(query, false); 46 | } 47 | 48 | 49 | } 50 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/serviceimpl/ProductCategoryBrandServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.serviceimpl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; 5 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 6 | import com.myshop.modules.product.entity.dos.ProductCategoryBrand; 7 | import com.myshop.modules.product.mapper.ProductCategoryBrandMapper; 8 | import com.myshop.modules.product.service.ProductCategoryBrandService; 9 | import org.springframework.stereotype.Service; 10 | 11 | import java.util.List; 12 | 13 | @Service 14 | public class ProductCategoryBrandServiceImpl extends ServiceImpl implements ProductCategoryBrandService { 15 | @Override 16 | public List getCategoryBrandsByBrandIds(List brandIds) { 17 | return this.list(new LambdaQueryWrapper().in(ProductCategoryBrand::getBrandId, brandIds)); 18 | } 19 | 20 | @Override 21 | public void deleteByProductCategoryId(String categoryId) { 22 | this.baseMapper.delete(new LambdaUpdateWrapper().eq(ProductCategoryBrand::getCategoryId, categoryId)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/serviceimpl/ProductCategorySpecificationServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.serviceimpl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import com.myshop.modules.product.entity.dos.ProductCategorySpecification; 6 | import com.myshop.modules.product.entity.dos.ProductSpecification; 7 | import com.myshop.modules.product.mapper.ProductCategorySpecificationMapper; 8 | import com.myshop.modules.product.service.ProductCategorySpecificationService; 9 | import org.springframework.stereotype.Service; 10 | 11 | import java.util.List; 12 | 13 | @Service 14 | public class ProductCategorySpecificationServiceImpl extends ServiceImpl implements ProductCategorySpecificationService { 15 | @Override 16 | public List getProductCategorySpecList(String categoryId) { 17 | return this.baseMapper.getProductCategorySpecList(categoryId); 18 | } 19 | 20 | @Override 21 | public void deleteByProductCategoryId(String categoryId) { 22 | this.baseMapper.delete(new LambdaQueryWrapper().eq(ProductCategorySpecification::getCategoryId, categoryId)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/serviceimpl/ProductGalleryServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.serviceimpl; 2 | 3 | import cn.hutool.json.JSONUtil; 4 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 5 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 6 | import com.myshop.modules.product.entity.dos.ProductGallery; 7 | import com.myshop.modules.product.mapper.ProductGalleryMapper; 8 | import com.myshop.modules.product.service.ProductGalleryService; 9 | import com.myshop.modules.system.entity.dos.Setting; 10 | import com.myshop.modules.system.entity.dto.ProductSetting; 11 | import com.myshop.modules.system.entity.enums.SettingEnum; 12 | import com.myshop.modules.system.service.SettingService; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.stereotype.Service; 15 | import org.springframework.transaction.annotation.Transactional; 16 | 17 | import java.util.List; 18 | 19 | @Service 20 | public class ProductGalleryServiceImpl extends ServiceImpl implements ProductGalleryService { 21 | 22 | @Autowired 23 | private SettingService settingService; 24 | 25 | 26 | @Override 27 | @Transactional(rollbackFor = Exception.class) 28 | public void add(List productGalleryList, String goodsId) { 29 | // Xóa thông tin album ảnh sản phẩm cũ 30 | this.baseMapper.delete(new QueryWrapper().eq("product_id", goodsId)); 31 | // Xử lý sau khi xác định trình chọn ảnh 32 | int i = 0; 33 | for (String origin : productGalleryList) { 34 | // Lấy album ảnh có tất cả ảnh thu nhỏ 35 | ProductGallery galley = this.getProductGallery(origin); 36 | galley.setProductId(goodsId); 37 | // Ảnh đầu tiên là ảnh mặc định 38 | galley.setIsDefault(i == 0 ? 1 : 0); 39 | i++; 40 | this.baseMapper.insert(galley); 41 | } 42 | } 43 | 44 | @Override 45 | public List productGalleryList(String productId) { 46 | return this.baseMapper.selectList(new QueryWrapper().eq("productId", productId)); 47 | } 48 | 49 | @Override 50 | public ProductGallery getProductGallery(String origin) { 51 | ProductGallery goodsGallery = new ProductGallery(); 52 | // Lấy cấu hình hệ thống sản phẩm để quyết định có cần phê duyệt hay không 53 | Setting setting = settingService.get(SettingEnum.PRODUCT_SETTING.name()); 54 | ProductSetting productSetting = JSONUtil.toBean(setting.getSettingValue(), ProductSetting.class); 55 | // Ảnh thu nhỏ 56 | String thumbnail = this.getUrl(origin, productSetting.getThumbnailImageWidth(), productSetting.getThumbnailImageHeight()); 57 | // Ảnh nhỏ 58 | String small = this.getUrl(origin, productSetting.getSmallImageWidth(), productSetting.getSmallImageHeight()); 59 | // Gán giá trị 60 | goodsGallery.setSmall(small); 61 | goodsGallery.setThumbnail(thumbnail); 62 | goodsGallery.setOriginal(origin); 63 | return goodsGallery; 64 | } 65 | 66 | 67 | /** 68 | * Tạo ảnh có kích thước đã định từ ảnh gốc 69 | * 70 | * @param url Liên kết 71 | * @param width Chiều rộng 72 | * @param height Chiều cao 73 | * @return 74 | */ 75 | private String getUrl(String url, Integer width, Integer height) { 76 | Setting setting = settingService.get(SettingEnum.OSS_SETTING.name()); 77 | //TODO: trien khai with nhieu oss 78 | return url; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/serviceimpl/ProductSpecificationServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.serviceimpl; 2 | 3 | import cn.hutool.json.JSONUtil; 4 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 5 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 6 | import com.myshop.common.enums.ResultCode; 7 | import com.myshop.common.exception.ServiceException; 8 | import com.myshop.modules.product.entity.dos.ProductCategorySpecification; 9 | import com.myshop.modules.product.entity.dos.ProductSpecification; 10 | import com.myshop.modules.product.mapper.ProductSpecificationMapper; 11 | import com.myshop.modules.product.service.ProductCategoryService; 12 | import com.myshop.modules.product.service.ProductCategorySpecificationService; 13 | import com.myshop.modules.product.service.ProductSpecificationService; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.stereotype.Service; 16 | 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | 20 | @Service 21 | public class ProductSpecificationServiceImpl extends ServiceImpl implements ProductSpecificationService { 22 | 23 | @Autowired 24 | private ProductCategorySpecificationService productCategorySpecificationService; 25 | /** 26 | * Phân loại 27 | */ 28 | @Autowired 29 | private ProductCategoryService productCategoryService; 30 | 31 | 32 | @Override 33 | public boolean deleteProductSpecification(List ids) { 34 | boolean result = false; 35 | for (String id : ids) { 36 | // Nếu thông số kỹ thuật này được liên kết với phân loại thì không được phép xóa 37 | List list = productCategorySpecificationService.list(new QueryWrapper().eq("product_specification_id", id)); 38 | if (!list.isEmpty()) { 39 | List categoryIds = new ArrayList<>(); 40 | list.forEach(item -> categoryIds.add(item.getCategoryId())); 41 | throw new ServiceException(ResultCode.PRODUCT_SPEC_DELETE_ERROR, JSONUtil.toJsonStr(productCategoryService.getProductCategoryNameByIds(categoryIds))); 42 | } 43 | // Xóa thông số kỹ thuật 44 | result = this.removeById(id); 45 | } 46 | return result; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/product/serviceimpl/ProductUnitServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.product.serviceimpl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.myshop.modules.product.entity.dos.ProductUnit; 5 | import com.myshop.modules.product.mapper.ProductUnitMapper; 6 | import com.myshop.modules.product.service.ProductUnitService; 7 | import org.springframework.stereotype.Service; 8 | 9 | @Service 10 | public class ProductUnitServiceImpl extends ServiceImpl implements ProductUnitService { 11 | } 12 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/search/utils/SqlFilter.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.search.utils; 2 | 3 | import com.myshop.common.utils.StringUtils; 4 | 5 | import java.util.regex.Matcher; 6 | import java.util.regex.Pattern; 7 | 8 | /** 9 | * Lọc từ khóa SQL 10 | */ 11 | public class SqlFilter { 12 | // Mẫu lọc SQL Injection 13 | static final String SQL_INJECTION_KEYWORDS_PATTERN = "(?i)(SELECT|FROM|WHERE|WHEN|CONCAT|AND|NOT|INSERT|UPDATE|DELETE" + "|HAVING|ORDER|ASC|DESC|LIKE|IN|ELSE|BETWEEN|IS|NULL|TRUE|FALSE" + "|JOIN|LEFT|RIGHT|UNION|INNER|OUTER|FULL|ON|AS|DISTINCT|COUNT" + "|MAX|MIN|SUM|AVG|IF|RAND|UPDATEXML|EXTRACTVALUE|LOAD_FILE|SLEEP|OFFSET|CASE|THEN|END)"; 14 | // OR ảnh hưởng đến trường sắp xếp sort, do đó tạm thời không lọc 15 | // CREATE ảnh hưởng đến trường sắp xếp phổ biến, CREATE_TIME, do đó tạm thời không lọc 16 | static final Pattern sqlKeywordPattern = Pattern.compile(SQL_INJECTION_KEYWORDS_PATTERN, Pattern.CASE_INSENSITIVE); 17 | 18 | 19 | /** 20 | * Từ khóa trùng khớp 21 | * 22 | * @param sql 23 | * @return 24 | */ 25 | public static Boolean checkSqlKeywords(String sql) { 26 | if (StringUtils.isEmpty(sql)) { 27 | return false; 28 | } 29 | Matcher matcher = sqlKeywordPattern.matcher(sql); 30 | return matcher.find(); 31 | } 32 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/store/entity/enums/StoreStatusEnum.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.store.entity.enums; 2 | 3 | /** 4 | * Trạng thái cửa hàng 5 | */ 6 | public enum StoreStatusEnum { 7 | /** 8 | * Đang mở 9 | */ 10 | OPEN("Đang mở"), 11 | /** 12 | * Cửa hàng đóng cửa 13 | */ 14 | CLOSED("Cửa hàng đóng cửa"), 15 | /** 16 | * Đang yêu cầu mở cửa hàng 17 | */ 18 | APPLY("Đang yêu cầu mở cửa hàng, chỉ cần hoàn thành bước đầu tiên là yêu cầu"), 19 | /** 20 | * Yêu cầu bị từ chối 21 | */ 22 | REFUSED("Yêu cầu bị từ chối"), 23 | /** 24 | * Đang xét duyệt 25 | */ 26 | APPLYING("Đang xét duyệt, đã gửi yêu cầu"); 27 | 28 | private final String description; 29 | 30 | StoreStatusEnum(String description) { 31 | this.description = description; 32 | } 33 | 34 | public String description() { 35 | return this.description; 36 | } 37 | 38 | public String value() { 39 | return this.name(); 40 | } 41 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/store/entity/vos/StoreVO.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.store.entity.vos; 2 | 3 | import com.myshop.modules.store.entity.dos.Store; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | 7 | /** 8 | * Thông tin cửa hàng 9 | */ 10 | @Data 11 | public class StoreVO extends Store { 12 | 13 | @ApiModelProperty(value = "Số lượng cảnh báo tồn kho") 14 | private Integer stockWarning; 15 | 16 | @ApiModelProperty(value = "Tên người dùng đăng nhập") 17 | private String nickName; 18 | 19 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/store/mapper/StoreMapper.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.store.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.myshop.modules.store.entity.dos.Store; 5 | 6 | public interface StoreMapper extends BaseMapper { 7 | } 8 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/store/service/StoreService.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.store.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.myshop.modules.store.entity.dos.Store; 5 | 6 | public interface StoreService extends IService { 7 | } 8 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/store/service/StoreServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.store.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.myshop.modules.store.entity.dos.Store; 5 | import com.myshop.modules.store.mapper.StoreMapper; 6 | import org.springframework.stereotype.Service; 7 | 8 | @Service 9 | public class StoreServiceImpl extends ServiceImpl implements StoreService { 10 | } 11 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/system/entity/dos/Setting.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.system.entity.dos; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import com.myshop.orm.BaseEntity; 5 | import io.swagger.annotations.ApiModel; 6 | import io.swagger.annotations.ApiModelProperty; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | 11 | /** 12 | * Cấu hình 13 | */ 14 | @Data 15 | @TableName("myshop_setting") 16 | @ApiModel(value = "Cấu hình") 17 | @NoArgsConstructor 18 | public class Setting extends BaseEntity { 19 | 20 | private static final long serialVersionUID = 1L; 21 | 22 | @ApiModelProperty(value = "Giá trị cấu hình") 23 | private String settingValue; 24 | 25 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/system/entity/dto/ProductSetting.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.system.entity.dto; 2 | 3 | 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * Cài đặt sản phẩm 11 | */ 12 | @Data 13 | public class ProductSetting implements Serializable { 14 | 15 | private static final long serialVersionUID = -4132785717179910025L; 16 | @ApiModelProperty(value = "Có bật phê duyệt sản phẩm hay không") 17 | private Boolean productCheck; 18 | 19 | @ApiModelProperty(value = "Chiều rộng ảnh nhỏ") 20 | private Integer smallImageWidth; 21 | 22 | @ApiModelProperty(value = "Chiều cao ảnh nhỏ") 23 | private Integer smallImageHeight; 24 | 25 | @ApiModelProperty(value = "Chiều rộng ảnh thu nhỏ") 26 | private Integer thumbnailImageWidth; 27 | 28 | @ApiModelProperty(value = "Chiều cao ảnh thu nhỏ") 29 | private Integer thumbnailImageHeight; 30 | 31 | @ApiModelProperty(value = "Chiều rộng ảnh gốc") 32 | private Integer originalImageWidth; 33 | 34 | @ApiModelProperty(value = "Chiều cao ảnh gốc") 35 | private Integer originalImageHeight; 36 | 37 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/system/entity/enums/SettingEnum.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.system.entity.enums; 2 | 3 | /** 4 | * Hằng số cài đặt hệ thống 5 | */ 6 | public enum SettingEnum { 7 | 8 | // Cài đặt sản phẩm 9 | PRODUCT_SETTING, 10 | //Cài đặt Oss 11 | OSS_SETTING; 12 | 13 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/system/mapper/SettingMapper.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.system.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.myshop.modules.system.entity.dos.Setting; 5 | 6 | public interface SettingMapper extends BaseMapper { 7 | } 8 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/system/service/SettingService.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.system.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.myshop.modules.system.entity.dos.Setting; 5 | import org.springframework.cache.annotation.CacheConfig; 6 | import org.springframework.cache.annotation.Cacheable; 7 | 8 | @CacheConfig(cacheNames = "{SETTING_SYSTEM}") 9 | public interface SettingService extends IService { 10 | /** 11 | * Lấy cấu hình theo key 12 | * 13 | * @param settingKey 14 | * @return 15 | */ 16 | @Cacheable(key = "#key") 17 | Setting get(String settingKey); 18 | } 19 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/modules/system/serviceimpl/SettingServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.myshop.modules.system.serviceimpl; 2 | 3 | 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import com.myshop.modules.system.entity.dos.Setting; 6 | import com.myshop.modules.system.mapper.SettingMapper; 7 | import com.myshop.modules.system.service.SettingService; 8 | import org.springframework.stereotype.Service; 9 | 10 | /** 11 | * Cài đặt lớp dịch vụ 12 | */ 13 | @Service 14 | public class SettingServiceImpl extends ServiceImpl implements SettingService { 15 | 16 | @Override 17 | public Setting get(String key) { 18 | return this.getById(key); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/orm/BaseEntity.java: -------------------------------------------------------------------------------- 1 | package com.myshop.orm; 2 | 3 | import com.baomidou.mybatisplus.annotation.FieldFill; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.fasterxml.jackson.annotation.JsonFormat; 7 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 8 | import lombok.AllArgsConstructor; 9 | import lombok.Data; 10 | import lombok.NoArgsConstructor; 11 | import org.springframework.data.annotation.CreatedBy; 12 | import org.springframework.data.annotation.CreatedDate; 13 | import org.springframework.data.annotation.LastModifiedBy; 14 | import org.springframework.data.annotation.LastModifiedDate; 15 | import org.springframework.data.elasticsearch.annotations.DateFormat; 16 | import org.springframework.data.elasticsearch.annotations.Field; 17 | import org.springframework.data.elasticsearch.annotations.FieldType; 18 | import org.springframework.format.annotation.DateTimeFormat; 19 | 20 | import java.io.Serializable; 21 | import java.util.Date; 22 | 23 | 24 | /** 25 | * Base Entity Class for Database 26 | * 27 | * @author vantrang 28 | * @since 2024/10/16 29 | */ 30 | @Data 31 | @JsonIgnoreProperties(value = {"handler", "fieldHandler"}) 32 | @AllArgsConstructor 33 | @NoArgsConstructor 34 | public abstract class BaseEntity implements Serializable { 35 | 36 | private static final long serialVersionUID = 1L; 37 | 38 | @TableId 39 | private String id; 40 | 41 | @CreatedBy 42 | @TableField(fill = FieldFill.INSERT) 43 | private String createBy; 44 | 45 | @CreatedDate 46 | @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") 47 | @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") 48 | @TableField(fill = FieldFill.INSERT) 49 | @Field(type = FieldType.Date, format = DateFormat.date, pattern = "yyyy-MM-dd HH:mm:ss || yyyy-MM-dd || yyyy/MM/dd HH:mm:ss|| yyyy/MM/dd ||epoch_millis") 50 | private Date createTime; 51 | 52 | @LastModifiedBy 53 | @TableField(fill = FieldFill.UPDATE) 54 | private String updateBy; 55 | 56 | @LastModifiedDate 57 | @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") 58 | @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") 59 | @TableField(fill = FieldFill.INSERT_UPDATE) 60 | @Field(type = FieldType.Date, format = DateFormat.date, pattern = "yyyy-MM-dd HH:mm:ss || yyyy-MM-dd || yyyy/MM/dd HH:mm:ss|| yyyy/MM/dd ||epoch_millis") 61 | private Date updateTime; 62 | 63 | @TableField(fill = FieldFill.INSERT) 64 | private Boolean deleteFlag; 65 | 66 | } 67 | -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/orm/IdBasedEntity.java: -------------------------------------------------------------------------------- 1 | package com.myshop.orm; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableId; 4 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import java.io.Serializable; 10 | 11 | /** 12 | * Base Entity Class for Database 13 | * 14 | * @author vantrang 15 | * @since 2024/10/16 16 | */ 17 | @Data 18 | @JsonIgnoreProperties(value = {"handler", "fieldHandler"}) 19 | @AllArgsConstructor 20 | @NoArgsConstructor 21 | public abstract class IdBasedEntity implements Serializable { 22 | 23 | private static final long serialVersionUID = 1L; 24 | 25 | @TableId 26 | private String id; 27 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/orm/mybatisplus/MybatisObjectHandler.java: -------------------------------------------------------------------------------- 1 | package com.myshop.orm.mybatisplus; 2 | 3 | import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; 4 | import org.apache.ibatis.reflection.MetaObject; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.stereotype.Component; 8 | 9 | /** 10 | * Field Auditing 11 | * 12 | * @author vantrang 13 | */ 14 | @Component 15 | public class MybatisObjectHandler implements MetaObjectHandler { 16 | 17 | @Override 18 | public void insertFill(MetaObject metaObject) { 19 | final Logger logger = LoggerFactory.getLogger(MybatisObjectHandler.class); 20 | //TODO: triển khai với các vai trò khác nhau 21 | } 22 | 23 | @Override 24 | public void updateFill(MetaObject metaObject) { 25 | 26 | //TODO: triển khai với các vai trò 27 | } 28 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/orm/mybatisplus/MybatisPlusConfig.java: -------------------------------------------------------------------------------- 1 | package com.myshop.orm.mybatisplus; 2 | 3 | import com.baomidou.mybatisplus.annotation.DbType; 4 | import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; 5 | import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; 6 | import org.mybatis.spring.annotation.MapperScan; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | /** 11 | * @author vantrang 12 | */ 13 | @Configuration 14 | @MapperScan({"com.myshop.modules.*.*.mapper", "com.myshop.modules.*.mapper"}) 15 | public class MybatisPlusConfig { 16 | /** 17 | * Plug-in phân trang, tự động xác định loại cơ sở dữ liệu 18 | */ 19 | @Bean 20 | public MybatisPlusInterceptor mybatisPlusInterceptor() { 21 | MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); 22 | interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); 23 | return interceptor; 24 | } 25 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/orm/mybatisplus/external/CustomBaseMapper.java: -------------------------------------------------------------------------------- 1 | package com.myshop.orm.mybatisplus.external; 2 | 3 | import java.util.List; 4 | 5 | 6 | /** 7 | * @author vantrang 8 | */ 9 | public interface CustomBaseMapper { 10 | 11 | 12 | /** 13 | * Chèn hàng loạt 14 | * 15 | * @param entityList 16 | * @return 17 | */ 18 | long insertBatchSomeColumn(List entityList); 19 | 20 | int insertIgnoreBatchAllColumn(List list); 21 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/orm/mybatisplus/external/CustomSqlInjector.java: -------------------------------------------------------------------------------- 1 | package com.myshop.orm.mybatisplus.external; 2 | 3 | import com.baomidou.mybatisplus.core.injector.AbstractMethod; 4 | import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector; 5 | import com.baomidou.mybatisplus.core.metadata.TableInfo; 6 | import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn; 7 | import org.springframework.stereotype.Component; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * @author vantrang 13 | */ 14 | @Component 15 | public class CustomSqlInjector extends DefaultSqlInjector { 16 | 17 | /** 18 | * Nếu bạn chỉ cần thêm phương thức, hãy giữ lại các phương thức đi kèm với mybatis plus. 19 | * Trước tiên, bạn có thể lấy super.getMethodList(), sau đó thêm add 20 | */ 21 | @Override 22 | public List getMethodList(Class mapperClass, TableInfo tableInfo) { 23 | // Lưu ý: Bộ tiêm SQL này kế thừa DefaultSqlInjector (bộ tiêm mặc định), gọi phương thức getMethodList của DefaultSqlInjector và giữ lại phương thức tích hợp sẵn của mybatis-plus. 24 | List methodList = super.getMethodList(mapperClass, tableInfo); 25 | // Tiêm InsertBatchSomeColumn 26 | // !t.isLogicDelete() có nghĩa là không xóa trường một cách logic, !"update_time".equals(t.getColumn()) có nghĩa là không cần trường có tên update_time, sẽ không có thao tác nào được thực hiện 27 | // MethodList.add(new InsertBatchSomeColumn(t -> !t.isLogicDelete() && !"update_time".equals(t.getColumn()))); 28 | // Để xóa t.isLogicDelete() một cách logic, mặc định không bắt buộc 29 | methodList.add(new InsertBatchSomeColumn(t -> !t.isLogicDelete())); 30 | methodList.add(new BulkInsertIgnoreAll("bulkInsertIgnoreAll")); 31 | return methodList; 32 | } 33 | } -------------------------------------------------------------------------------- /myshop-framework/src/main/java/com/myshop/orm/util/PageUtil.java: -------------------------------------------------------------------------------- 1 | package com.myshop.orm.util; 2 | 3 | import cn.hutool.core.text.CharSequenceUtil; 4 | import com.baomidou.mybatisplus.core.metadata.OrderItem; 5 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 6 | import com.myshop.common.vo.PageVO.PageVO; 7 | import com.myshop.modules.search.utils.SqlFilter; 8 | import lombok.extern.slf4j.Slf4j; 9 | 10 | /** 11 | * Công cụ phân trang 12 | */ 13 | @Slf4j 14 | public class PageUtil { 15 | 16 | // Có nguy cơ tiêm order by, giới hạn độ dài 17 | static final Integer MAX_ORDER_BY_LENGTH = 20; 18 | 19 | /** 20 | * Phân trang Mybatis-Plus 21 | * 22 | * @param page Phân trang VO 23 | * @param Kiểu dữ liệu chung 24 | * @return Phân trang phản hồi 25 | */ 26 | public static Page buildPage(PageVO page) { 27 | 28 | int currentPage = page.getCurrentPage(); 29 | int pageLimit = page.getPageLimit(); 30 | String sortBy = page.getSortBy(); 31 | String sortOrder = page.getSortOrder(); 32 | 33 | if (currentPage < 1) { 34 | currentPage = 1; 35 | } 36 | if (pageLimit < 1) { 37 | pageLimit = 10; 38 | } 39 | if (pageLimit > 100) { 40 | pageLimit = 100; 41 | } 42 | 43 | Page p = new Page<>(currentPage, pageLimit); 44 | 45 | if (CharSequenceUtil.isNotBlank(sortBy)) { 46 | 47 | if (sortBy.length() > MAX_ORDER_BY_LENGTH || SqlFilter.checkSqlKeywords(sortBy)) { 48 | log.error("Độ dài trường sắp xếp vượt quá giới hạn hoặc chứa từ khóa sql, vui lòng chú ý: {}", sortBy); 49 | return p; 50 | } 51 | 52 | boolean isAsc = false; 53 | if (!CharSequenceUtil.isBlank(sortOrder)) { 54 | if ("desc".equals(sortOrder.toLowerCase())) { 55 | isAsc = false; 56 | } else if ("asc".equals(sortOrder.toLowerCase())) { 57 | isAsc = true; 58 | } 59 | } 60 | 61 | if (isAsc) { 62 | p.addOrder(OrderItem.asc(sortBy)); 63 | } else { 64 | p.addOrder(OrderItem.desc(sortBy)); 65 | } 66 | 67 | } 68 | return p; 69 | } 70 | 71 | } -------------------------------------------------------------------------------- /myshop-module-buyer/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.myshop 8 | my-shop-parent 9 | ${revision} 10 | ../pom.xml 11 | 12 | 13 | myshop-module-buyer 14 | 15 | 16 | 17 | com.myshop 18 | myshop-framework 19 | ${revision} 20 | 21 | 22 | 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-maven-plugin 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /myshop-module-buyer/src/main/java/com/myshop/BuyerApplicationApi.java: -------------------------------------------------------------------------------- 1 | package com.myshop; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cache.annotation.EnableCaching; 6 | import org.springframework.scheduling.annotation.EnableAsync; 7 | 8 | /** 9 | * Buyer API 10 | * 11 | * @author vantrang 12 | */ 13 | @SpringBootApplication 14 | @EnableCaching 15 | @EnableAsync 16 | public class BuyerApplicationApi { 17 | public static void main(String[] args) { 18 | SpringApplication.run(BuyerApplicationApi.class, args); 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /myshop-module-buyer/src/main/java/com/myshop/controller/identity/BuyerMemberController.java: -------------------------------------------------------------------------------- 1 | package com.myshop.controller.identity; 2 | 3 | import com.myshop.common.enums.ResultUtil; 4 | import com.myshop.common.vo.ResultMessage; 5 | import com.myshop.modules.member.service.MemberService; 6 | import io.swagger.annotations.Api; 7 | import io.swagger.annotations.ApiImplicitParam; 8 | import io.swagger.annotations.ApiImplicitParams; 9 | import io.swagger.annotations.ApiOperation; 10 | import jakarta.validation.constraints.NotNull; 11 | import lombok.extern.slf4j.Slf4j; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.web.bind.annotation.PostMapping; 14 | import org.springframework.web.bind.annotation.RequestMapping; 15 | import org.springframework.web.bind.annotation.RequestParam; 16 | import org.springframework.web.bind.annotation.RestController; 17 | 18 | /** 19 | * Phiên bản người mua, giao diện thành viên 20 | */ 21 | @Slf4j 22 | @RestController 23 | @Api(tags = "Phiên bản người mua, giao diện thành viên") 24 | @RequestMapping("/buyer/identity/member") 25 | public class BuyerMemberController { 26 | 27 | @Autowired 28 | private MemberService memberService; 29 | 30 | @ApiOperation(value = "Giao diện đăng nhập") 31 | @ApiImplicitParams({@ApiImplicitParam(name = "username", value = "Tên đăng nhập", required = true, paramType = "query"), @ApiImplicitParam(name = "password", value = "Mật khẩu", required = true, paramType = "query")}) 32 | @PostMapping("/login") 33 | public ResultMessage login(@NotNull(message = "Tên đăng nhập không được để trống") @RequestParam String username, @NotNull(message = "Mật khẩu không được để trống") @RequestParam String password) { 34 | //TODO: trien khai xac minh bang captcha truoc khi cho login 35 | return ResultUtil.data(this.memberService.login(username, password)); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /myshop-module-buyer/src/main/java/com/myshop/controller/identity/ProductCategoryBuyerController.java: -------------------------------------------------------------------------------- 1 | package com.myshop.controller.identity; 2 | 3 | 4 | import com.myshop.common.enums.ResultUtil; 5 | import com.myshop.common.vo.ResultMessage; 6 | import com.myshop.modules.product.entity.vos.ProductCategoryVO; 7 | import com.myshop.modules.product.service.ProductCategoryService; 8 | import io.swagger.annotations.Api; 9 | import io.swagger.annotations.ApiImplicitParam; 10 | import io.swagger.annotations.ApiOperation; 11 | import jakarta.validation.constraints.NotNull; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.web.bind.annotation.GetMapping; 14 | import org.springframework.web.bind.annotation.PathVariable; 15 | import org.springframework.web.bind.annotation.RequestMapping; 16 | import org.springframework.web.bind.annotation.RestController; 17 | 18 | import java.util.List; 19 | 20 | 21 | /** 22 | * Giao diện phân loại hàng hóa dành cho người mua 23 | */ 24 | @RestController 25 | @Api(tags = "Giao diện phân loại hàng hóa dành cho người mua") 26 | @RequestMapping("/buyer/product/category") 27 | public class ProductCategoryBuyerController { 28 | /** 29 | * Phân loại hàng hóa 30 | */ 31 | @Autowired 32 | private ProductCategoryService productCategoryService; 33 | 34 | @ApiOperation(value = "Lấy danh sách phân loại hàng hóa") 35 | @ApiImplicitParam(name = "parentId", value = "ID phân loại cha, tất cả phân loại là: 0", required = true, dataType = "Long", paramType = "path") 36 | @GetMapping(value = "/{parentId}") 37 | public ResultMessage> getAllCategories(@NotNull(message = "ID phân loại không được để trống") @PathVariable String parentId) { 38 | return ResultUtil.data(productCategoryService.listSubCategories(parentId)); 39 | } 40 | } -------------------------------------------------------------------------------- /myshop-module-buyer/src/main/java/com/myshop/controller/product/ProductBuyerController.java: -------------------------------------------------------------------------------- 1 | package com.myshop.controller.product; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.myshop.common.enums.ResultUtil; 5 | import com.myshop.common.vo.ResultMessage; 6 | import com.myshop.modules.product.entity.dos.Product; 7 | import com.myshop.modules.product.entity.dos.ProductSearchParams; 8 | import com.myshop.modules.product.entity.vos.ProductVO; 9 | import com.myshop.modules.product.service.ProductService; 10 | import io.swagger.annotations.Api; 11 | import io.swagger.annotations.ApiImplicitParam; 12 | import io.swagger.annotations.ApiOperation; 13 | import jakarta.validation.constraints.NotNull; 14 | import lombok.extern.slf4j.Slf4j; 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.web.bind.annotation.GetMapping; 17 | import org.springframework.web.bind.annotation.PathVariable; 18 | import org.springframework.web.bind.annotation.RequestMapping; 19 | import org.springframework.web.bind.annotation.RestController; 20 | 21 | /** 22 | * Giao diện sản phẩm cho người mua 23 | */ 24 | @Slf4j 25 | @Api(tags = "Giao diện sản phẩm cho người mua") 26 | @RestController 27 | @RequestMapping("/buyer/product/product") 28 | public class ProductBuyerController { 29 | 30 | @Autowired 31 | private ProductService productService; 32 | 33 | @ApiOperation(value = "Lấy danh sách sản phẩm phân trang") 34 | @GetMapping 35 | public ResultMessage> getByPage(ProductSearchParams productSearchParams) { 36 | return ResultUtil.data(productService.getByParams(productSearchParams)); 37 | } 38 | 39 | @ApiOperation(value = "Lấy thông tin sản phẩm theo ID") 40 | @ApiImplicitParam(name = "productId", value = "ID sản phẩm", required = true, paramType = "path", dataType = "Long") 41 | @GetMapping(value = "/get/{productId}") 42 | public ResultMessage get(@NotNull(message = "ID sản phẩm không được để trống") @PathVariable("productId") String productId) { 43 | return ResultUtil.data(productService.getProductVO(productId)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /myshop-module-buyer/src/main/java/com/myshop/security/SecurityConfigForBuyer.java: -------------------------------------------------------------------------------- 1 | package com.myshop.security; 2 | 3 | import com.myshop.cache.Cache; 4 | import com.myshop.common.properties.IgnoredUrlsProperties; 5 | import com.myshop.common.security.InvalidAuthenticationEntryPoint; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.security.authentication.AuthenticationManager; 9 | import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; 10 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 11 | import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; 12 | import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer; 13 | import org.springframework.security.config.http.SessionCreationPolicy; 14 | import org.springframework.security.web.AuthenticationEntryPoint; 15 | import org.springframework.security.web.SecurityFilterChain; 16 | import org.springframework.security.web.access.AccessDeniedHandler; 17 | import org.springframework.web.cors.CorsConfigurationSource; 18 | 19 | public class SecurityConfigForBuyer { 20 | 21 | @Autowired 22 | private IgnoredUrlsProperties ignoredUrlsProperties; 23 | 24 | @Autowired 25 | private CorsConfigurationSource corsConfigurationSource; 26 | 27 | /** 28 | * Handling of insufficient permissions 29 | */ 30 | @Autowired 31 | private InvalidAuthenticationEntryPoint invalidAuthenticationEntryPoint; 32 | 33 | /** 34 | * Authentication failure handling class Bean 35 | */ 36 | @Autowired 37 | private AuthenticationEntryPoint authenticationEntryPoint; 38 | 39 | /** 40 | * Insufficient permissions for processor bean 41 | */ 42 | @Autowired 43 | private AccessDeniedHandler accessDeniedHandler; 44 | 45 | @Autowired 46 | private Cache cache; 47 | 48 | @Bean 49 | public SecurityFilterChain securityFilterChain(HttpSecurity http, AuthenticationConfiguration authenticationConfiguration) throws Exception { 50 | AuthenticationManager authenticationManager = authenticationConfiguration.getAuthenticationManager(); 51 | 52 | http.authorizeHttpRequests(authorizeRequests -> authorizeRequests.requestMatchers(ignoredUrlsProperties.getUrls().toArray(new String[0])).permitAll().anyRequest().authenticated()).headers(c -> c.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable)).logout(logout -> logout.permitAll()) 53 | //Enable cross-domain 54 | .cors(cors -> cors.configurationSource(corsConfigurationSource)) 55 | //CSRF is disabled because Session is not used 56 | .csrf(AbstractHttpConfigurer::disable).sessionManagement(sessionManagement -> sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS)).exceptionHandling(c -> c.authenticationEntryPoint(authenticationEntryPoint).accessDeniedHandler(accessDeniedHandler)).addFilter(new AuthenticationFilterForBuyer(authenticationManager, cache)); 57 | 58 | return http.build(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /myshop-module-manager/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.myshop 8 | my-shop-parent 9 | ${revision} 10 | ../pom.xml 11 | 12 | 13 | myshop-module-manager 14 | 15 | 16 | 17 | com.myshop 18 | myshop-framework 19 | ${revision} 20 | 21 | 22 | 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-maven-plugin 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /myshop-module-manager/src/main/java/com/myshop/ManagerApplicationApi.java: -------------------------------------------------------------------------------- 1 | package com.myshop; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cache.annotation.EnableCaching; 6 | import org.springframework.scheduling.annotation.EnableAsync; 7 | 8 | 9 | /** 10 | * Manager API 11 | * 12 | * @author vantrang 13 | */ 14 | @SpringBootApplication 15 | @EnableCaching 16 | @EnableAsync 17 | public class ManagerApplicationApi { 18 | public static void main(String[] args) { 19 | SpringApplication.run(ManagerApplicationApi.class, args); 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /myshop-module-manager/src/main/java/com/myshop/controller/identity/AdminUserManagementController.java: -------------------------------------------------------------------------------- 1 | package com.myshop.controller.identity; 2 | 3 | import com.myshop.common.enums.ResultUtil; 4 | import com.myshop.common.security.token.Token; 5 | import com.myshop.common.vo.ResultMessage; 6 | import com.myshop.modules.permission.service.AdminUserService; 7 | import io.swagger.annotations.Api; 8 | import io.swagger.annotations.ApiOperation; 9 | import jakarta.validation.constraints.NotNull; 10 | import lombok.extern.slf4j.Slf4j; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.validation.annotation.Validated; 13 | import org.springframework.web.bind.annotation.PostMapping; 14 | import org.springframework.web.bind.annotation.RequestMapping; 15 | import org.springframework.web.bind.annotation.RequestParam; 16 | import org.springframework.web.bind.annotation.RestController; 17 | 18 | 19 | /** 20 | * API Quản trị viên 21 | * 22 | * @author vantrang 23 | */ 24 | @Slf4j 25 | @RestController 26 | @Api(tags = "Quản trị viên") 27 | @RequestMapping("/manager/identity/user") 28 | @Validated 29 | public class AdminUserManagementController { 30 | 31 | @Autowired 32 | private AdminUserService adminUserService; 33 | 34 | @PostMapping(value = "/login") 35 | @ApiOperation(value = "Đăng nhập quản trị viên") 36 | public ResultMessage login(@NotNull(message = "Tên đăng nhập không được để trống") @RequestParam String username, @NotNull(message = "Mật khẩu không được để trống") @RequestParam String password) { 37 | //TODO: triển khai mã xác nhận trước khi cho login 38 | return ResultUtil.data(adminUserService.login(username, password)); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /myshop-module-manager/src/main/java/com/myshop/controller/product/ProductCategoryParameterGroupManagerController.java: -------------------------------------------------------------------------------- 1 | package com.myshop.controller.product; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.myshop.common.enums.ResultCode; 5 | import com.myshop.common.enums.ResultUtil; 6 | import com.myshop.common.exception.ServiceException; 7 | import com.myshop.common.vo.ResultMessage; 8 | import com.myshop.modules.product.entity.dos.ProductCategoryParameterGroup; 9 | import com.myshop.modules.product.entity.dos.ProductParameters; 10 | import com.myshop.modules.product.entity.vos.ProductParameterGroupVO; 11 | import com.myshop.modules.product.service.ProductCategoryParameterGroupService; 12 | import com.myshop.modules.product.service.ProductParametersService; 13 | import io.swagger.annotations.Api; 14 | import io.swagger.annotations.ApiImplicitParam; 15 | import io.swagger.annotations.ApiOperation; 16 | import org.springframework.beans.factory.annotation.Autowired; 17 | import org.springframework.validation.annotation.Validated; 18 | import org.springframework.web.bind.annotation.*; 19 | 20 | import java.util.List; 21 | 22 | /** 23 | * Giao diện quản lý, liên kết nhóm tham số phân loại 24 | */ 25 | @RestController 26 | @Api(tags = "Giao diện quản lý, liên kết nhóm tham số phân loại") 27 | @RequestMapping("/manager/product/categoryParameters") 28 | public class ProductCategoryParameterGroupManagerController { 29 | 30 | @Autowired 31 | private ProductParametersService productParametersService; 32 | 33 | @Autowired 34 | private ProductCategoryParameterGroupService productCategoryParameterGroupService; 35 | 36 | @ApiOperation(value = "Truy vấn thông tin tham số được liên kết trong một phân loại") 37 | @GetMapping(value = "/{categoryId}") 38 | @ApiImplicitParam(value = "ID phân loại", required = true, dataType = "String", paramType = "path") 39 | public ResultMessage> getProductCategoryParam(@PathVariable String categoryId) { 40 | return ResultUtil.data(productCategoryParameterGroupService.getProductCategoryParams(categoryId)); 41 | } 42 | 43 | @ApiOperation(value = "Lưu dữ liệu") 44 | @PostMapping 45 | public ResultMessage saveOrUpdate(@Validated ProductCategoryParameterGroup productCategoryParameterGroup) { 46 | if (productCategoryParameterGroupService.save(productCategoryParameterGroup)) { 47 | return ResultUtil.data(productCategoryParameterGroup); 48 | } 49 | throw new ServiceException(ResultCode.PRODUCT_CATEGORY_PARAMETER_SAVE_ERROR); 50 | } 51 | 52 | @ApiOperation(value = "Cập nhật dữ liệu") 53 | @PutMapping 54 | public ResultMessage update(@Validated ProductCategoryParameterGroup productCategoryParameterGroup) { 55 | 56 | if (productCategoryParameterGroupService.updateById(productCategoryParameterGroup)) { 57 | return ResultUtil.data(productCategoryParameterGroup); 58 | } 59 | throw new ServiceException(ResultCode.PRODUCT_CATEGORY_PARAMETER_UPDATE_ERROR); 60 | } 61 | 62 | @ApiOperation(value = "Xóa nhóm tham số theo id") 63 | @ApiImplicitParam(name = "id", value = "ID của nhóm tham số", required = true, dataType = "String", paramType = "path") 64 | @DeleteMapping(value = "/{id}") 65 | public ResultMessage del(@PathVariable String id) { 66 | productParametersService.remove(new QueryWrapper().eq("group_id", id)); 67 | productCategoryParameterGroupService.removeById(id); 68 | return ResultUtil.success(); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /myshop-module-manager/src/main/java/com/myshop/controller/product/ProductManagerController.java: -------------------------------------------------------------------------------- 1 | package com.myshop.controller.product; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.myshop.common.aop.annotation.AntiDuplicateSubmission; 5 | import com.myshop.common.enums.ResultCode; 6 | import com.myshop.common.enums.ResultUtil; 7 | import com.myshop.common.exception.ServiceException; 8 | import com.myshop.common.vo.ResultMessage; 9 | import com.myshop.modules.product.entity.dos.Product; 10 | import com.myshop.modules.product.entity.dos.ProductSearchParams; 11 | import com.myshop.modules.product.entity.enums.ProductAuthEnum; 12 | import com.myshop.modules.product.entity.enums.ProductStatusEnum; 13 | import com.myshop.modules.product.service.ProductService; 14 | import io.swagger.annotations.Api; 15 | import io.swagger.annotations.ApiImplicitParam; 16 | import io.swagger.annotations.ApiImplicitParams; 17 | import io.swagger.annotations.ApiOperation; 18 | import jakarta.validation.constraints.NotEmpty; 19 | import org.springframework.beans.factory.annotation.Autowired; 20 | import org.springframework.web.bind.annotation.*; 21 | 22 | import java.util.Arrays; 23 | import java.util.List; 24 | 25 | @RestController 26 | @Api(tags = "Hệ thống quản trị, API quản lý sản phẩm") 27 | @RequestMapping("/manager/product/product") 28 | public class ProductManagerController { 29 | 30 | @Autowired 31 | ProductService productService; 32 | 33 | @ApiOperation(value = "Phân trang lấy danh sách sản phẩm chờ duyệt") 34 | @GetMapping(value = "/auth/pending") 35 | public ResultMessage> getAuthPage(ProductSearchParams productSearchParams) { 36 | productSearchParams.setIsApproved(ProductAuthEnum.PENDING.name()); 37 | return ResultUtil.data(productService.queryByParams(productSearchParams)); 38 | } 39 | 40 | 41 | @AntiDuplicateSubmission 42 | @ApiOperation(value = "Quản trị viên đưa sản phẩm lên kệ", notes = "Sử dụng khi quản trị viên đưa sản phẩm lên kệ") 43 | @PutMapping(value = "/{productId}/up") 44 | @ApiImplicitParams({@ApiImplicitParam(name = "productId", value = "ID sản phẩm", required = true, allowMultiple = true)}) 45 | public ResultMessage upProduct(@PathVariable List productId) { 46 | if (Boolean.TRUE.equals(productService.updateProductMarketAble(productId, ProductStatusEnum.UPPER, ""))) { 47 | return ResultUtil.success(); 48 | } 49 | throw new ServiceException(ResultCode.PRODUCT_UPPER_ERROR); 50 | } 51 | 52 | @AntiDuplicateSubmission 53 | @ApiOperation(value = "Quản trị viên đưa sản phẩm xuống kệ", notes = "Quản trị viên sử dụng chức năng này để đưa sản phẩm xuống kệ") 54 | @ApiImplicitParams({@ApiImplicitParam(name = "productId", value = "ID sản phẩm", required = true, paramType = "query", allowMultiple = true), @ApiImplicitParam(name = "reason", value = "Lý do xuống kệ", required = true, paramType = "query")}) 55 | @PutMapping(value = "/{productId}/under") 56 | public ResultMessage underProduct(@PathVariable String productId, @NotEmpty(message = "Lý do xuống kệ không được để trống") @RequestParam String reason) { 57 | List productIds = Arrays.asList(productId.split(",")); 58 | if (Boolean.TRUE.equals(productService.managerUpdateProductMarketAble(productIds, ProductStatusEnum.DOWN, reason))) { 59 | return ResultUtil.success(); 60 | } 61 | throw new ServiceException(ResultCode.PRODUCT_UNDER_ERROR); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /myshop-module-manager/src/main/java/com/myshop/controller/product/ProductParameterManagerController.java: -------------------------------------------------------------------------------- 1 | package com.myshop.controller.product; 2 | 3 | import com.myshop.common.enums.ResultCode; 4 | import com.myshop.common.enums.ResultUtil; 5 | import com.myshop.common.exception.ServiceException; 6 | import com.myshop.common.vo.ResultMessage; 7 | import com.myshop.modules.product.entity.dos.ProductParameters; 8 | import com.myshop.modules.product.service.ProductParametersService; 9 | import io.swagger.annotations.Api; 10 | import io.swagger.annotations.ApiImplicitParam; 11 | import io.swagger.annotations.ApiOperation; 12 | import jakarta.validation.Valid; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.web.bind.annotation.*; 15 | 16 | /** 17 | * Giao diện quản lý nhóm tham số liên kết với danh mục, dành cho quản trị viên 18 | */ 19 | @RestController 20 | @Api(tags = "Giao diện quản lý nhóm tham số liên kết với danh mục, dành cho quản trị viên") 21 | @RequestMapping("/manager/product/parameters") 22 | public class ProductParameterManagerController { 23 | 24 | @Autowired 25 | private ProductParametersService productParametersService; 26 | 27 | @ApiOperation(value = "Thêm tham số") 28 | @PostMapping 29 | public ResultMessage add(@Valid ProductParameters productParameters) { 30 | if (productParametersService.save(productParameters)) { 31 | return ResultUtil.data(productParameters); 32 | } 33 | throw new ServiceException(ResultCode.PRODUCT_PARAMETER_SAVE_ERROR); 34 | 35 | } 36 | 37 | @ApiOperation(value = "Chỉnh sửa tham số") 38 | @PutMapping 39 | public ResultMessage update(@Valid ProductParameters productParameters) { 40 | if (productParametersService.updateProductParameter(productParameters)) { 41 | return ResultUtil.data(productParameters); 42 | } 43 | throw new ServiceException(ResultCode.PRODUCT_PARAMETER_UPDATE_ERROR); 44 | } 45 | 46 | @ApiOperation(value = "Xóa tham số theo ID") 47 | @ApiImplicitParam(name = "id", value = "ID của tham số", required = true, paramType = "path") 48 | @DeleteMapping(value = "/{id}") 49 | public ResultMessage del(@PathVariable String id) { 50 | productParametersService.removeById(id); 51 | return ResultUtil.success(); 52 | 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /myshop-module-manager/src/main/java/com/myshop/controller/product/ProductSpecificationManagerController.java: -------------------------------------------------------------------------------- 1 | package com.myshop.controller.product; 2 | 3 | import cn.hutool.core.text.CharSequenceUtil; 4 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 5 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 6 | import com.myshop.common.enums.ResultUtil; 7 | import com.myshop.common.vo.PageVO.PageVO; 8 | import com.myshop.common.vo.ResultMessage; 9 | import com.myshop.modules.product.entity.dos.ProductSpecification; 10 | import com.myshop.modules.product.service.ProductSpecificationService; 11 | import com.myshop.orm.util.PageUtil; 12 | import io.swagger.annotations.Api; 13 | import io.swagger.annotations.ApiImplicitParam; 14 | import io.swagger.annotations.ApiOperation; 15 | import jakarta.validation.Valid; 16 | import org.springframework.beans.factory.annotation.Autowired; 17 | import org.springframework.web.bind.annotation.*; 18 | 19 | import java.util.List; 20 | 21 | /** 22 | * Giao diện quản lý sản phẩm, thông số kỹ thuật 23 | */ 24 | @RestController 25 | @Api(tags = "Giao diện quản lý sản phẩm, thông số kỹ thuật") 26 | @RequestMapping("/manager/product/spec") 27 | public class ProductSpecificationManagerController { 28 | 29 | @Autowired 30 | private ProductSpecificationService productSpecificationService; 31 | 32 | @GetMapping("/all") 33 | @ApiOperation(value = "Lấy tất cả thông số kỹ thuật có thể sử dụng") 34 | public ResultMessage> getAll() { 35 | return ResultUtil.data(productSpecificationService.list()); 36 | } 37 | 38 | @GetMapping 39 | @ApiOperation(value = "Tìm kiếm thông số kỹ thuật") 40 | public ResultMessage> page(String specName, PageVO page) { 41 | LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); 42 | lambdaQueryWrapper.like(CharSequenceUtil.isNotEmpty(specName), ProductSpecification::getSpecName, specName); 43 | return ResultUtil.data(productSpecificationService.page(PageUtil.buildPage(page), lambdaQueryWrapper)); 44 | } 45 | 46 | @PostMapping 47 | @ApiOperation(value = "Lưu thông số kỹ thuật") 48 | public ResultMessage add(@Valid ProductSpecification specification) { 49 | productSpecificationService.save(specification); 50 | return ResultUtil.success(); 51 | } 52 | 53 | @PutMapping("/{id}") 54 | @ApiOperation(value = "Thay đổi thông số kỹ thuật") 55 | public ResultMessage update(@Valid ProductSpecification specification, @PathVariable String id) { 56 | specification.setId(id); 57 | return ResultUtil.data(productSpecificationService.saveOrUpdate(specification)); 58 | } 59 | 60 | @DeleteMapping("/{ids}") 61 | @ApiImplicitParam(name = "ids", value = "ID thông số kỹ thuật", required = true, dataType = "String", allowMultiple = true, paramType = "path") 62 | @ApiOperation(value = "Xóa hàng loạt") 63 | public ResultMessage delAll(@PathVariable List ids) { 64 | return ResultUtil.data(productSpecificationService.deleteProductSpecification(ids)); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /myshop-module-manager/src/main/java/com/myshop/controller/product/ProductUnitManagerController.java: -------------------------------------------------------------------------------- 1 | package com.myshop.controller.product; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.myshop.common.enums.ResultUtil; 5 | import com.myshop.common.vo.PageVO.PageVO; 6 | import com.myshop.common.vo.ResultMessage; 7 | import com.myshop.modules.product.entity.dos.ProductUnit; 8 | import com.myshop.modules.product.service.ProductUnitService; 9 | import com.myshop.orm.util.PageUtil; 10 | import io.swagger.annotations.Api; 11 | import io.swagger.annotations.ApiImplicitParam; 12 | import io.swagger.annotations.ApiOperation; 13 | import jakarta.validation.Valid; 14 | import jakarta.validation.constraints.NotNull; 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.web.bind.annotation.*; 17 | 18 | import java.util.List; 19 | 20 | /** 21 | * Giao diện quản lý đơn vị đo lường sản phẩm cho quản trị viên 22 | */ 23 | @RestController 24 | @Api(tags = "Giao diện quản lý đơn vị đo lường sản phẩm cho quản trị viên") 25 | @RequestMapping("/manager/product/productUnit") 26 | public class ProductUnitManagerController { 27 | 28 | @Autowired 29 | private ProductUnitService productUnitService; 30 | 31 | @ApiOperation(value = "Phân trang lấy danh sách đơn vị đo lường sản phẩm") 32 | @GetMapping 33 | public ResultMessage> getByPage(PageVO pageVO) { 34 | return ResultUtil.data(productUnitService.page(PageUtil.buildPage(pageVO))); 35 | } 36 | 37 | @ApiOperation(value = "Lấy thông tin đơn vị đo lường sản phẩm") 38 | @ApiImplicitParam(name = "id", value = "ID của đơn vị đo lường", required = true, paramType = "path") 39 | @GetMapping("/{id}") 40 | public ResultMessage getById(@NotNull @PathVariable String id) { 41 | return ResultUtil.data(productUnitService.getById(id)); 42 | } 43 | 44 | @ApiOperation(value = "Thêm đơn vị đo lường sản phẩm") 45 | @PostMapping 46 | public ResultMessage add(@Valid ProductUnit productUnit) { 47 | productUnitService.save(productUnit); 48 | return ResultUtil.data(productUnit); 49 | } 50 | 51 | @ApiOperation(value = "Chỉnh sửa đơn vị đo lường sản phẩm") 52 | @ApiImplicitParam(name = "id", value = "ID của đơn vị đo lường", required = true, paramType = "path") 53 | @PutMapping("/{id}") 54 | public ResultMessage update(@NotNull @PathVariable String id, @Valid ProductUnit productUnit) { 55 | productUnit.setId(id); 56 | productUnitService.updateById(productUnit); 57 | return ResultUtil.data(productUnit); 58 | } 59 | 60 | @ApiOperation(value = "Xóa đơn vị đo lường sản phẩm") 61 | @ApiImplicitParam(name = "ids", value = "Danh sách ID của đơn vị đo lường", required = true, paramType = "path") 62 | @DeleteMapping("/{ids}") 63 | public ResultMessage remove(@NotNull @PathVariable List ids) { 64 | productUnitService.removeByIds(ids); 65 | return ResultUtil.success(); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /myshop-module-manager/src/main/resources/application.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anonystick/JAVA-ecommerce-backend-api-MEMBER/874cb3e2a133d9e4678dde9da9cf28999adcbd67/myshop-module-manager/src/main/resources/application.yml -------------------------------------------------------------------------------- /myshop-module-store/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.myshop 8 | my-shop-parent 9 | ${revision} 10 | ../pom.xml 11 | 12 | 13 | myshop-module-store 14 | 15 | 16 | 17 | com.myshop 18 | myshop-framework 19 | ${revision} 20 | 21 | 22 | org.springframework.security 23 | spring-security-config 24 | 25 | 26 | 27 | 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-maven-plugin 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /myshop-module-store/src/main/java/com/myshop/StoreApplicationApi.java: -------------------------------------------------------------------------------- 1 | package com.myshop; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cache.annotation.EnableCaching; 6 | import org.springframework.scheduling.annotation.EnableAsync; 7 | 8 | /** 9 | * Store API 10 | * 11 | * @author vantrang 12 | */ 13 | @SpringBootApplication 14 | @EnableCaching 15 | @EnableAsync 16 | public class StoreApplicationApi { 17 | public static void main(String[] args) { 18 | SpringApplication.run(StoreApplicationApi.class, args); 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /myshop-module-store/src/main/java/com/myshop/controller/product/ProductCategoryParameterGroupStoreController.java: -------------------------------------------------------------------------------- 1 | package com.myshop.controller.product; 2 | 3 | import com.myshop.modules.product.entity.vos.ProductParameterGroupVO; 4 | import com.myshop.modules.product.service.ProductCategoryParameterGroupService; 5 | import io.swagger.annotations.Api; 6 | import io.swagger.annotations.ApiImplicitParam; 7 | import io.swagger.annotations.ApiOperation; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.PathVariable; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | import java.util.List; 15 | 16 | /** 17 | * Giao diện quản lý nhóm tham số liên kết danh mục cho cửa hàng 18 | */ 19 | @RestController 20 | @Api(tags = "Giao diện quản lý nhóm tham số liên kết danh mục cho cửa hàng") 21 | @RequestMapping("/store/product/categoryParameters") 22 | public class ProductCategoryParameterGroupStoreController { 23 | 24 | @Autowired 25 | private ProductCategoryParameterGroupService productCategoryParameterGroupService; 26 | 27 | @ApiOperation(value = "Truy vấn thông tin tham số được liên kết với danh mục") 28 | @GetMapping(value = "/{id}") 29 | @ApiImplicitParam(name = "id", value = "ID danh mục", required = true, dataType = "String", paramType = "path") 30 | public List getCategoryParam(@PathVariable("id") String categoryId) { 31 | return productCategoryParameterGroupService.getProductCategoryParams(categoryId); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /myshop-module-store/src/main/java/com/myshop/controller/product/ProductSpecificationStoreController.java: -------------------------------------------------------------------------------- 1 | package com.myshop.controller.product; 2 | 3 | import com.myshop.modules.product.entity.dos.ProductSpecification; 4 | import com.myshop.modules.product.service.ProductCategorySpecificationService; 5 | import io.swagger.annotations.Api; 6 | import io.swagger.annotations.ApiOperation; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | import org.springframework.web.bind.annotation.PathVariable; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | import java.util.List; 14 | 15 | /** 16 | * Giao diện quản lý cửa hàng, thông số kỹ thuật 17 | */ 18 | @RestController 19 | @Api(tags = "Giao diện quản lý cửa hàng, thông số kỹ thuật") 20 | @RequestMapping("/store/product/spec") 21 | public class ProductSpecificationStoreController { 22 | 23 | @Autowired 24 | private ProductCategorySpecificationService productCategorySpecificationService; 25 | 26 | @GetMapping(value = "/{categoryId}") 27 | @ApiOperation(value = "Lấy thông số kỹ thuật phân loại") 28 | public List getProductSpecifications(@PathVariable String categoryId) { 29 | return productCategorySpecificationService.getProductCategorySpecList(categoryId); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /myshop-module-store/src/main/java/com/myshop/controller/product/ProductStoreController.java: -------------------------------------------------------------------------------- 1 | package com.myshop.controller.product; 2 | 3 | import com.myshop.common.enums.ResultUtil; 4 | import com.myshop.common.vo.ResultMessage; 5 | import com.myshop.modules.product.entity.dto.ProductOperationDTO; 6 | import com.myshop.modules.product.service.ProductService; 7 | import io.swagger.annotations.Api; 8 | import io.swagger.annotations.ApiOperation; 9 | import jakarta.validation.Valid; 10 | import lombok.extern.slf4j.Slf4j; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.web.bind.annotation.PostMapping; 13 | import org.springframework.web.bind.annotation.RequestBody; 14 | import org.springframework.web.bind.annotation.RequestMapping; 15 | import org.springframework.web.bind.annotation.RestController; 16 | 17 | /** 18 | * Giao diện sản phẩm cho cửa hàng 19 | */ 20 | @RestController 21 | @Slf4j 22 | @Api(tags = "Giao diện sản phẩm cho cửa hàng") 23 | @RequestMapping("/store/product/product") 24 | public class ProductStoreController { 25 | 26 | @Autowired 27 | private ProductService productService; 28 | 29 | @ApiOperation(value = "Thêm sản phẩm mới") 30 | @PostMapping(value = "/add", consumes = "application/json", produces = "application/json") 31 | public ResultMessage save(@Valid @RequestBody ProductOperationDTO productOperationDTO) { 32 | productService.addProduct(productOperationDTO); 33 | return ResultUtil.success(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /myshop-module-store/src/main/java/com/myshop/controller/product/ProductUnitStoreController.java: -------------------------------------------------------------------------------- 1 | package com.myshop.controller.product; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.myshop.common.enums.ResultUtil; 5 | import com.myshop.common.vo.PageVO.PageVO; 6 | import com.myshop.common.vo.ResultMessage; 7 | import com.myshop.modules.product.entity.dos.ProductUnit; 8 | import com.myshop.modules.product.service.ProductUnitService; 9 | import com.myshop.orm.util.PageUtil; 10 | import io.swagger.annotations.Api; 11 | import io.swagger.annotations.ApiOperation; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.web.bind.annotation.GetMapping; 14 | import org.springframework.web.bind.annotation.RequestMapping; 15 | import org.springframework.web.bind.annotation.RestController; 16 | 17 | /** 18 | * Giao diện quản lý đơn vị đo lường sản phẩm cho cửa hàng 19 | */ 20 | @RestController 21 | @Api(tags = "Giao diện quản lý đơn vị đo lường sản phẩm cho cửa hàng") 22 | @RequestMapping("/store/product/productUnit") 23 | public class ProductUnitStoreController { 24 | 25 | @Autowired 26 | private ProductUnitService productUnitService; 27 | 28 | @ApiOperation(value = "Phân trang lấy danh sách đơn vị đo lường sản phẩm") 29 | @GetMapping 30 | public ResultMessage> getByPage(PageVO pageVO) { 31 | return ResultUtil.data(productUnitService.page(PageUtil.buildPage(pageVO))); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /myshop-module-store/src/main/resources/application.yml : -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anonystick/JAVA-ecommerce-backend-api-MEMBER/874cb3e2a133d9e4678dde9da9cf28999adcbd67/myshop-module-store/src/main/resources/application.yml -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 3.3.4 9 | 10 | 11 | com.myshop 12 | my-shop-parent 13 | ${revision} 14 | pom 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | myshop-framework 24 | myshop-module-buyer 25 | myshop-module-manager 26 | myshop-module-store 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 17 36 | 4.3 37 | UTF-8 38 | UTF-8 39 | 3.5.5 40 | 3.0.3 41 | 4.1.1 42 | 4.0.1 43 | 1.2.16 44 | 4.1.1 45 | 1.18.30 46 | 3.15.6 47 | 5.8.24 48 | 2.0.51 49 | 0.11.2 50 | 3.0.3 51 | 1.0.3 52 | 3.0.0 53 | 1.8.5 54 | 2.6.6 55 | 7.17.3 56 | 4.3 57 | 1.21 58 | 5.1.0 59 | 5.1.0 60 | 1.7.36 61 | 62 | 63 | 64 | 65 | 66 | org.apache.maven.plugins 67 | maven-compiler-plugin 68 | 69 | true 70 | 71 | 72 | 73 | 74 | 75 | 76 | --------------------------------------------------------------------------------